--routeMakeBlue.mesa --1> tidy up rectangle overlaps not visable to user -- Remove complete overlaps by deleting something -- Reduce or extend partial overlaps so all connecting things -- overlap by the width of one wire (2 or 3 lambda) -- Break long wires into segments ending at contacts or junctions --2> turn as much as possible of the red wires to blue -- only works when contacts extend up and right from junctions. -- PROBLEM current logic doesn't break red wires at junctions DIRECTORY RouteDefs; RouteMakeBlue:PROGRAM IMPORTS RouteDefs EXPORTS RouteDefs =BEGIN OPEN RouteDefs; Error:SIGNAL=CODE; --Silicon:TYPE=RECORD[pos,pos2:CoordL_[0,0],level:What_both, -- solid:BOOLEAN_FALSE, circuit:Circuit_0]; list:SiliconListPtr_NIL; big:Lambda; MakeBlue:PUBLIC PROCEDURE=BEGIN --IF TRUE THEN RETURN; big_problem.chipSize.x; MakeBlueX[]; --EnumerateSilicon[Rotate]; --MakeBlueX[]; --EnumerateSilicon[RotateBack]; END; Rotate:PROCEDURE[s:SiliconPtr]=BEGIN t:Lambda_s.pos.y; s.pos.y_big-s.pos2.x; s.pos2.x_s.pos2.y; s.pos2.y_big-s.pos.x; s.pos.x_t; END; RotateBack:PROCEDURE[s:SiliconPtr]=BEGIN t:Lambda_s.pos.x; s.pos.x_big-s.pos2.y; s.pos2.y_s.pos2.x; s.pos2.x_big-s.pos.y; s.pos.y_t; END; MakeBlueX:PROCEDURE=BEGIN EnumerateSilicon[TidyDoubleContacts]; EnumerateSilicon[TidyWireToContacts]; EnumerateSilicon[TidyWireToWire]; EnumerateSilicon[TidyButtingEnds]; EnumerateSilicon[SplitWiresAtContacts]; ScavengeSilicon[]; EnumerateSilicon[MakeRedBlue]; EnumerateSilicon[TidyWireToContacts]; ScavengeSilicon[]; END; TidyDoubleContacts:PROCEDURE[s:SiliconPtr]=BEGIN IF s.level#both THEN RETURN; FOR sl:SiliconListPtr_layout,sl.t UNTIL sl=NIL DO s2:SiliconPtr=sl.h; IF s2.level=both AND s2.pos=s.pos AND s2#s THEN Destroy[s2]; ENDLOOP; END; TidyWireToContacts:PROCEDURE[s:SiliconPtr]=BEGIN seenRed,seenBlue:BOOLEAN_FALSE; IF s.level#both THEN RETURN; FOR sl:SiliconListPtr_layout,sl.t UNTIL sl=NIL DO s2:SiliconPtr=sl.h; w:INTEGER=IF s2.level=red THEN 2 ELSE 3; IF s2.level=both THEN LOOP; IF s2.pos2.y-s2.pos.y=w AND s2.pos.y-s.pos.y IN [0..4-w] THEN BEGIN IF s2.pos.x-s.pos.x IN [0..4] THEN s2.pos.x_s.pos.x; IF s2.pos2.x-s.pos.x IN [0..4] THEN s2.pos2.x_s.pos.x+w; IF s2.level=red THEN seenRed_TRUE ELSE seenBlue_TRUE; END; IF s2.pos2.x-s2.pos.x=w AND s2.pos.x-s.pos.x IN [0..4-w] THEN BEGIN IF s2.pos.y IN [s.pos.y..s.pos.y+4] THEN s2.pos.y_s.pos.y; IF s2.pos2.y IN [s.pos.y..s.pos.y+4] THEN s2.pos2.y_s.pos.y+w; IF s2.level=red THEN seenRed_TRUE ELSE seenBlue_TRUE; END; ENDLOOP; IF ~seenRed OR ~seenBlue THEN Destroy[s]; END; TidyWireToWire:PROCEDURE[s:SiliconPtr]=BEGIN w:INTEGER=IF s.level=red THEN 2 ELSE 3; IF s.level=both THEN RETURN; IF ~(s.pos2.y-s.pos.y=w) THEN RETURN; FOR sl:SiliconListPtr_layout,sl.t UNTIL sl=NIL DO s2:SiliconPtr=sl.h; IF s2.level#s.level THEN LOOP; IF ~(s2.pos2.x-s2.pos.x=w) THEN LOOP; IF s=s2 THEN LOOP; IF s.pos.y IN [s2.pos.y-w..s2.pos2.y+w) THEN BEGIN IF s.pos.x IN [s2.pos.x..s2.pos2.x] THEN s.pos.x_s2.pos.x; IF s.pos2.x IN [s2.pos.x..s2.pos2.x] THEN s.pos2.x_s2.pos2.x; END; IF s2.pos.x IN [s.pos.x-w..s.pos2.x+w) THEN BEGIN IF s2.pos.y IN [s.pos.y..s.pos2.y] THEN s2.pos.y_s.pos.y; IF s2.pos2.y IN [s.pos.y..s.pos2.y] THEN s2.pos2.y_s.pos2.y; END; ENDLOOP; END; SplitWiresAtContacts:PROCEDURE[s:SiliconPtr]=BEGIN w:INTEGER=IF s.level=red THEN 2 ELSE 3; IF s.level=both THEN RETURN; IF s.pos2.y-s.pos.y=w THEN FOR sl:SiliconListPtr_layout,sl.t UNTIL sl=NIL DO s2:SiliconPtr=sl.h; IF s2.pos.x IN (s.pos.x..s.pos2.x-w) AND s.pos.y IN (s2.pos.y-w-w..s2.pos2.y+w) AND (s2.level=both OR s2.level=s.level AND s.pos2.y#s.pos.y+w) THEN SplitWiresAtContacts[SplitWire[s,s2.pos.x,TRUE]]; ENDLOOP ELSE FOR sl:SiliconListPtr_layout,sl.t UNTIL sl=NIL DO s2:SiliconPtr=sl.h; IF s2.pos.y IN (s.pos.y..s.pos2.y-w) AND s.pos.x IN (s2.pos.x-w-w..s2.pos2.x+w) AND (s2.level=both OR s2.level=s.level AND s.pos2.x#s.pos.x+w) THEN SplitWiresAtContacts[SplitWire[s,s2.pos.y,FALSE]]; ENDLOOP; END; SplitWire:PROCEDURE[s:SiliconPtr,where:Lambda,hor:BOOLEAN] RETURNS[s2:SiliconPtr]=BEGIN w:INTEGER=IF s.level=red THEN 2 ELSE 3; listS:SiliconListPtr_AllocateList[]; s2_AllocateSilicon[]; s2^_s^; listS^_[s2,layout]; layout_listS; IF hor THEN {s.pos2.x_where+w; s2.pos.x_where} ELSE {s.pos2.y_where+w; s2.pos.y_where} END; TidyButtingEnds:PROCEDURE[s:SiliconPtr]=BEGIN w:INTEGER=IF s.level=red THEN 2 ELSE 3; IF s.level=both THEN RETURN; FOR sl:SiliconListPtr_layout,sl.t UNTIL sl=NIL DO s2:SiliconPtr=sl.h; SELECT TRUE FROM s2.level#s.level OR s2=s => LOOP; s2.pos.y=s.pos.y AND s2.pos2.y=s.pos2.y => SELECT TRUE FROM s2.pos.x<=s.pos.x AND s2.pos2.x>=s.pos2.x => {Destroy[s]; RETURN}; s2.pos.x>=s.pos.x AND s2.pos2.x<=s.pos2.x => {Destroy[s2]; LOOP}; s2.pos.xIF s2.pos2.x>=s.pos.x THEN s.pos_s2.pos ELSE LOOP; ENDCASE=>IF s.pos2.x >=s2.pos.x THEN s.pos2_s2.pos2 ELSE LOOP; s2.pos.x=s.pos.x AND s2.pos2.x=s.pos2.x => SELECT TRUE FROM s2.pos.y<=s.pos.y AND s2.pos2.y>=s.pos2.y => {Destroy[s]; RETURN}; s2.pos.y>=s.pos.y AND s2.pos2.y<=s.pos2.y => {Destroy[s2]; LOOP}; s2.pos.yIF s2.pos2.y>=s.pos.y THEN s.pos_s2.pos ELSE LOOP; ENDCASE=>IF s.pos2.y >=s2.pos.y THEN s.pos2_s2.pos2 ELSE LOOP; ENDCASE=>LOOP; Destroy[s2]; TidyButtingEnds[s]; RETURN; ENDLOOP; END; Stuff:TYPE=RECORD[where:CoordL,red,blue:Four,con,passing:SiliconPtr_NIL, cellNearby,onCell:BOOLEAN_FALSE]; Four:TYPE=RECORD[n,s,e,w:SiliconPtr_NIL]; l,r:Stuff_[]; progress:BOOLEAN; thisWire:SiliconPtr_NIL;--to save passing it MakeRedBlue:PROCEDURE[s:SiliconPtr]=BEGIN LastStuff:PROCEDURE[p:POINTER TO Stuff] RETURNS[b:BOOLEAN]= {b_IF hor THEN p.where.x>=s.pos2.x-2 ELSE p.where.y>=s.pos2.y-2}; hor:BOOLEAN=s.pos2.y-s.pos.y=2; IF s.level#red THEN RETURN; thisWire_s; MakeList[s]; progress_FALSE; WhatsAtL[hor,s.pos]; UNTIL LastStuff[@l] DO WhatsAtR[hor,s]; IF hor AND r.where.x>s.pos2.x-2 THEN Error; IF ~hor AND r.where.y>s.pos2.y-2 THEN Error; IF hor THEN ProcessH[s] ELSE ProcessV[s]; IF s.level#red OR s.pos=outOfSight OR LastStuff[@r] THEN EXIT; IF ~progress OR r.where=[s.pos2.x-2,s.pos2.y-2] THEN l_r ELSE WhatsAtL[hor,r.where]; ENDLOOP; ScavengeList[]; END; WhatsAtL:PROCEDURE[hor:BOOLEAN,pos:CoordL]=BEGIN l_[]; l.where_pos; FOR sl:SiliconListPtr_list,sl.t UNTIL sl=NIL DO s:SiliconPtr=sl.h; parallel:BOOLEAN=IF hor THEN s.pos2.y-s.pos.y<4 ELSE s.pos2.x-s.pos.x<4; IF s.pos.y=pos.y AND s.pos.x IN [pos.x-2..pos.x+2] THEN SELECT s.level FROM both=>l.con_s; red =>{IF parallel THEN l.red.e_s ELSE l.red.n_s}; blue=>{IF parallel THEN l.blue.e_s ELSE l.blue.n_s}; ENDCASE=>Error ELSE SELECT s.level FROM red=>IF s.pos2.y=pos.y+2 AND s.pos2.x IN [pos.x-2..pos.x+4] THEN {IF parallel THEN l.red.w_s ELSE l.red.s_s}; blue=>BEGIN IF s.pos2.y=pos.y+3 AND s.pos2.x IN [pos.x-2..pos.x+4] THEN {IF parallel THEN l.blue.w_s ELSE l.blue.s_s} ELSE IF pos.x IN (s.pos.x-7..s.pos2.x+3) AND pos.y IN (s.pos.y-7..s.pos2.y+3) AND (l.passing=NIL OR parallel) THEN l.passing_s; END; ENDCASE; ENDLOOP; CellNearby[@l]; END; WhatsAtR:PROCEDURE[hor:BOOLEAN,ss:SiliconPtr]=BEGIN end:CoordL=[ss.pos2.x-2,ss.pos2.y-2]; pos:CoordL=[l.where.x+(IF hor THEN 3 ELSE 0),l.where.y]; w:CoordL_end; FOR dummy:INTEGER IN [0..2) DO r_[]; FOR sl:SiliconListPtr_list,sl.t UNTIL sl=NIL DO s:SiliconPtr=sl.h; h:INTEGER=SELECT s.level FROM blue=>3,red=>2,ENDCASE=>4; sEnd:CoordL=[s.pos2.x-h,s.pos2.y-h]; color:POINTER TO Four=IF s.level=blue THEN @r.blue ELSE @r.red; parallel:BOOLEAN = hor=(s.pos2.y-s.pos.y<4); IF s=ss THEN LOOP; IF s.level=both THEN BEGIN IF hor THEN BEGIN IF s.pos.y#pos.y THEN LOOP; IF s.pos.x IN (pos.x..w.x) THEN {r_[]; w.x_s.pos.x; Error}; END ELSE BEGIN IF s.pos.x#pos.x THEN LOOP; IF s.pos.y IN (pos.y..w.y) THEN {r_[]; w.y_s.pos.y; Error}; END; IF s.pos.y=w.y AND s.pos.x-w.x IN [-2..2] THEN r.con_s; LOOP; END; IF hor THEN BEGIN IF s.level=blue AND pos.y IN (s.pos.y-7..s.pos2.y+3) AND pos.y#s.pos.y AND pos.y#s.pos2.y-3 THEN BEGIN IF s.pos.x IN (pos.x..w.x) THEN {r_[]; w.x_s.pos.x}; IF s.pos.x =w.x THEN r.passing_s; END; IF pos.y NOT IN [s.pos.y..s.pos2.y-h] THEN LOOP; IF ~parallel THEN BEGIN IF s.pos.x IN (pos.x..w.x) THEN {r_[]; w.x_s.pos.x}; IF s.pos.x-w.x IN [0..2] AND s.pos.y=w.y THEN color.n_s; IF s.pos.x-w.x IN [0..2] AND s.pos2.y=w.y+h THEN color.s_s; END; END ELSE BEGIN IF s.level=blue AND pos.x IN (s.pos.x-7..s.pos2.x+3) AND pos.x#s.pos.x AND pos.x#s.pos2.x-3 THEN BEGIN IF s.pos.y IN (pos.y..w.y) THEN {r_[]; w.y_s.pos.y}; IF s.pos.y=w.y THEN r.passing_s; END; IF pos.x NOT IN [s.pos.x..s.pos2.x-h] THEN LOOP; IF ~parallel THEN BEGIN IF s.pos.y IN (pos.y..w.y) THEN {r_[]; w.y_s.pos.y}; IF s.pos.y=w.x AND s.pos.x=w.x THEN color.e_s; IF s.pos.x=w.x AND s.pos2.x=w.x+h THEN color.w_s; END; END; IF parallel THEN {IF s.pos=w THEN color.e_s; IF sEnd=w THEN color.w_s} ELSE {IF s.pos=w THEN color.n_s; IF sEnd=w THEN color.s_s}; ENDLOOP; ENDLOOP; IF w=end THEN r.red.w_ss; r.where_w; CellNearby[@r]; END; CellNearby:PROCEDURE[stuff:POINTER TO Stuff]=BEGIN pos:CoordL=stuff.where; stuff.cellNearby_FALSE; stuff.onCell_FALSE; FOR cl:CellListPtr_problem.cells,cl.t UNTIL cl=NIL DO cell:CellPtr=cl.h; IF ~ ( pos.x-cell.pos.x IN [-6..cell.sizeL.x+2] AND pos.y-cell.pos.y IN [-6..cell.sizeL.y+2]) THEN LOOP; IF (thisWire.pos.y>cell.pos.y+cell.sizeL.y OR thisWire.pos2.ycell.pos.x+cell.sizeL.x OR thisWire.pos2.x=newx2-k THEN RETURN; IF noRedLeft THEN l.con.pos.x_newx2 ELSE NewContact[newx2]; IF noRedLeft AND (l.blue.n=NIL AND l.blue.s=NIL AND l.blue.w#NIL) THEN BEGIN l.blue.w.pos2.x_newx2+3; IF buttR THEN Destroy[s] ELSE s.pos.x_newx2; END ELSE {IF ~noBlueRight THEN ExtendRight[]}; END; IF l.con=NIL AND r.con#NIL THEN BEGIN --9 cases here k:INTEGER=IF noRedRight THEN 0 ELSE 14; IF ~noBlueLeft AND r.where.x<=newx+k THEN RETURN; IF noRedRight THEN r.con.pos.x_newx ELSE NewContact[newx]; IF noRedRight AND (r.blue.n=NIL AND r.blue.s=NIL AND r.blue.w#NIL) THEN BEGIN r.blue.w.pos.x_newx; IF buttL THEN Destroy[s] ELSE s.pos2.x_newx+2; END ELSE {IF ~noBlueLeft THEN ExtendLeft[]}; END; IF l.con=NIL AND r.con=NIL THEN BEGIN IF newx2=newy2-k THEN RETURN; IF noRedLeft THEN l.con.pos.y_newy2 ELSE NewContact[newy2]; IF noRedLeft AND (l.blue.n=NIL AND l.blue.s=NIL AND l.blue.w#NIL) THEN BEGIN l.blue.w.pos2.y_newy2+3; IF buttR THEN Destroy[s] ELSE s.pos.y_newy2; END ELSE {IF ~noBlueRight THEN ExtendRight[]}; END; IF l.con=NIL AND r.con#NIL THEN BEGIN --9 cases here k:INTEGER=IF noRedRight THEN 0 ELSE 14; IF ~noBlueLeft AND r.where.y<=newy+k THEN RETURN; IF noRedRight THEN r.con.pos.y_newy ELSE NewContact[newy]; IF noRedRight AND (r.blue.n=NIL AND r.blue.s=NIL AND r.blue.w#NIL) THEN BEGIN r.blue.w.pos.y_newy; IF buttL THEN Destroy[s] ELSE s.pos2.y_newy+2; END ELSE {IF ~noBlueLeft THEN ExtendLeft[]}; END; IF l.con=NIL AND r.con=NIL THEN BEGIN IF newy2