--routeSilicon.mesa DIRECTORY RouteDefs; RouteSilicon:PROGRAM IMPORTS RouteDefs EXPORTS RouteDefs =BEGIN OPEN RouteDefs; Speed:TYPE=ARRAY [0..9) OF Lambda; SpeedPtr:TYPE=POINTER TO Speed; --none of these are true globals, they are just used by everybody. speed1,speed2,speedy1,speedy2:SpeedPtr; spaceB,topL:Lambda_0; Error:SIGNAL=CODE; wow:INTEGER=1; -- Main Code DebugPrint:PROCEDURE= {t:BOOLEAN=chipmonk; chipmonk_FALSE; PrintAll[]; chipmonk_t}; DoSilicon:PUBLIC CtlProc=BEGIN speed1S, speed2S, speedy1S, speedy2S:Speed; speed1_@speed1S; speed2_@speed2S; speedy1_@speedy1S; speedy2_@speedy2S; IF layout#NIL THEN Error; EnumerateChannels[ChanSilicon]; EnumerateInters[InterSilicon]; MakeBlue[]; ChipmonkSilicon[]; IF ~ chipmonk THEN PrintAll[]; IF ~ chipmonk THEN ShowSilicon[]; RETURN[-1]; END; ChanSilicon:PROCEDURE[rect:RectanglePtr]=BEGIN h:BOOLEAN=rect.orient=hor; topL_IF h THEN rect.sizeL.y ELSE rect.sizeL.x; spaceB_IF h THEN rect.margins.s+rect.levelers.s ELSE rect.margins.e+rect.levelers.e; EnumerateRuns[rect,SetRunEnd]; EnumerateRuns[rect,LayRun]; EnumerateConns[rect,LayConn]; END; SetRunEnd:PROCEDURE[rect:RectanglePtr,run:RunPtr]=BEGIN x:Lambda=rect.pos.x; y:Lambda=rect.pos.y; max:Lambda=IF rect.orient=hor THEN rect.sizeL.x ELSE rect.sizeL.y; run.startOffX_0; run.endOffX_max; IF run.start=-1 THEN BEGIN IF rect.nature#culDeSacL THEN run.startOffX_7*run.startOff ELSE BEGIN e:EventPtr_FindEvent[rect,run]; u:Lambda=Rot[rect,run.run]; --run v:Lambda=Rot[rect,e.offset]; --event s:BOOLEAN=e.level#red; run.startOffX_IF s AND u=v THEN 0 ELSE 3; IF rect.orient=hor THEN BEGIN IF s AND u#v THEN MakeBlueWire[TRUE,x,v,6]; IF ~s THEN {MakeRedWire[TRUE,x,v,5]; MakeContact[x+3,v]}; IF u#v THEN MakeBlueWire[FALSE,x+3,MIN[u,v],ABS[u-v]+3]; END ELSE BEGIN IF s AND u#v THEN MakeBlueWire[FALSE,v,y,6]; IF ~s THEN {MakeRedWire[FALSE,v,y,5]; MakeContact[v,y+3]}; IF u#v THEN MakeBlueWire[TRUE,MIN[u,v],y+3,ABS[u-v]+3]; END; END; END; IF run.end =bigRun THEN BEGIN IF rect.nature#culDeSacR THEN run.endOffX _max+7*run.endOff ELSE BEGIN e:EventPtr_FindEvent[rect,run]; u:Lambda=Rot[rect,run.run]; --run v:Lambda=Rot[rect,e.offset]; --event s:BOOLEAN=e.level#red; run.endOffX_IF s AND u=v THEN max ELSE max-3; IF rect.orient=hor THEN BEGIN IF s AND u#v THEN MakeBlueWire[TRUE,max-6,v,6]; IF ~s THEN {MakeRedWire[TRUE,max-5,v,5]; MakeContact[max-7,v]}; IF u#v THEN MakeBlueWire[FALSE,max-6,MIN[u,v],ABS[u-v]+3]; END ELSE BEGIN IF s AND u#v THEN MakeBlueWire[FALSE,v,max-6,6]; IF ~s THEN {MakeRedWire[FALSE,v,max-5,5]; MakeContact[v,max-7]}; IF u#v THEN MakeBlueWire[TRUE,MIN[u,v],max-6,ABS[u-v]+3]; END; END; END; IF run.end =-1 THEN run.endOffX _7*run.endOff; IF run.start=bigRun THEN run.startOffX_max+7*run.startOff; IF run.start=run.end THEN RETURN; FOR cl:ConnListPtr_rect.conns,cl.t UNTIL cl=NIL DO conn:ConnPtr=cl.h; d:Lambda=conn.lambdaX; SELECT TRUE FROM conn.circuit#run.circuit => LOOP; conn.event=-1 => LOOP; conn.event=bigRun => LOOP; conn.event=run.start =>run.startOffX_d; conn.event=run.end =>run.endOffX_d; ENDCASE=>LOOP; IF run.run NOT IN (conn.start.. conn.end) THEN LOOP; IF rect.orient=hor THEN MakeContact[x+d,Rot[rect,run.run]] ELSE MakeContact[Rot[rect,run.run]+wow,y+d]; ENDLOOP; END; FindEvent:PROCEDURE[rect:RectanglePtr,run:RunPtr] RETURNS[ans:EventPtr]=BEGIN Sub:PROCEDURE[rect:RectanglePtr,e:EventPtr]= {IF (e.where=left OR e.where=right) AND e.circuit=run.circuit THEN ans_e}; ans_NIL; EnumerateEvents[rect,Sub]; END; LayRun:PROCEDURE[rect:RectanglePtr,run:RunPtr]=BEGIN h:BOOLEAN=rect.orient=hor; x:Lambda=IF h THEN rect.pos.x+run.startOffX ELSE Rot[rect,run.run]-3; y:Lambda=IF h THEN Rot[rect,run.run] ELSE rect.pos.y+run.startOffX; MakeBlueWire[h, x, y, run.endOffX-run.startOffX+3]; END; LayConn:PROCEDURE[rect:RectanglePtr,conn:ConnPtr]=BEGIN h:BOOLEAN=(rect.orient=hor); Jog:PROCEDURE[wh:Where,yy,d:Lambda] RETURNS[new:Lambda]=BEGIN new_yy; IF wh=bottom AND conn.start#-1 OR wh=top AND conn.end#bigRun THEN BEGIN xt1:Lambda=IF h THEN x3 ELSE yy-(w+1); yt1:Lambda=IF h THEN yy ELSE x3; IF conn.level=red THEN MakeContact[xt1,yt1]; END ELSE BEGIN c2:EventPtr=IF ce.where=wh THEN ce ELSE ce.opposite; x2:Lambda=(IF h THEN rect.pos.x ELSE rect.pos.y)+c2.offset; t:Lambda=ABS[x3-x2]; IF t=0 THEN RETURN; new_yy+d; BEGIN xt1:Lambda=IF h THEN MIN[x2,x3] ELSE new-w; yt1:Lambda=IF h THEN new ELSE MIN[x2,x3]; xt2:Lambda=IF h THEN x2 ELSE MIN[new-w,yy]; yt2:Lambda=IF h THEN MIN[new,yy] ELSE x2; doOne[ h,xt1,yt1,t+w]; doOne[~h,xt2,yt2,w2]; END; END; END; ce:EventPtr=conn.eventPtr; w:Lambda=IF conn.level=blue THEN 3 ELSE 2; w2:Lambda=w+w; doOne:DoOne=IF conn.level=blue THEN MakeBlueWire ELSE MakeRedWire; x3:Lambda=(IF h THEN rect.pos.x ELSE rect.pos.y)+conn.lambdaX; ys:Lambda=Jog[bottom,Rot[rect,conn.start],IF h THEN w ELSE -w]; ye:Lambda=Jog[top ,Rot[rect,conn.end] ,IF h THEN -w2 ELSE w2]; doOne[~h,IF h THEN x3 ELSE ye,IF h THEN ys ELSE x3,ABS[ye-ys]] END; DoOne:TYPE=PROCEDURE[hor:BOOLEAN,x,y,l:Lambda]; ChipmonkSilicon:PROCEDURE=BEGIN Sub:PROCEDURE[s:SiliconPtr]=BEGIN h:Lambda=s.pos2.y-s.pos.y; w:Lambda=s.pos2.x-s.pos.x; hor:BOOLEAN=h<4; l:Lambda=IF hor THEN w ELSE h; SELECT s.level FROM blue=>PlotBlueWire[hor,s.pos.x,s.pos.y,l]; red=>PlotRedWire[hor,s.pos.x,s.pos.y,l]; both=>PlotBlueRedContact[s.pos.x,s.pos.y]; ENDCASE; END; IF ~chipmonk THEN RETURN; EnumerateCells[PlotCell]; StartPlot[]; EnumerateSilicon[Sub]; EndPlot[]; END; PrintAll:PROCEDURE=BEGIN ShowLabel[" ALL"]; EnumerateChannels[RectanglePrint]; EnumerateInters[RectanglePrint]; END; RectanglePrint:PROCEDURE[rect:RectanglePtr]=BEGIN Return[]; Return[]; ShowDecimal[rect.channelNo,"ch "]; ShowPoint[" pos ",rect.pos.x,rect.pos.y]; ShowPoint[" sizeL ",rect.sizeL.x,rect.sizeL.y]; ShowPoint[" sizeC ",rect.sizeC.x,rect.sizeC.y]; ShowString[SELECT rect.orient FROM hor=>" H ", vert=>" V ", inter=> "INT ", ENDCASE=>" X "]; ShowString[SELECT rect.nature FROM channel=>" CH ", inter=>" IN ", culDeSacR=> " CR ", culDeSacL=> " CL ", bend5=> " B5 ", bend9=> " B9 ", bend6=> " B6 ", bend10=> " B10 ", wallL=> " WL ", wallR=> " WR ", ENDCASE=>" X "]; FOR rl:RunListPtr_rect.runs,rl.t UNTIL rl=NIL DO run:RunPtr=rl.h; Return[]; ShowDecimal[run.circuit," cir "]; ShowDecimal[run.run," run "]; ShowPoint[" ",run.start,run.end]; ShowPoint[" ",run.startOff,run.endOff]; ShowPoint[" ",run.startOffX,run.endOffX]; ENDLOOP; FOR cl:ConnListPtr_rect.conns,cl.t UNTIL cl=NIL DO conn:ConnPtr=cl.h; Return[]; ShowDecimal[conn.circuit," cir "]; ShowDecimal[ conn.event," conn "]; ShowDecimal[conn.lambdaX," "]; ShowPoint[" ",conn.start,conn.end]; ShowString[SELECT conn.level FROM red=>" r ", blue=>" b ", ENDCASE=>" x "]; ShowDecimal[conn.offset," offset "]; ShowString[" "]; ShowString[SELECT conn.startKind FROM left=>"l", right=>"r", ENDCASE=>"x"]; ShowString[SELECT conn.endKind FROM left=>"l", right=>"r", ENDCASE=>"x"]; ENDLOOP; FOR el:EventListPtr_rect.events,el.t UNTIL el=NIL DO event:EventPtr=el.h; Return[]; ShowDecimal[event.circuit," cir "]; ShowDecimal[event.index," event "]; ShowString[SELECT event.where FROM top=>" top ", left=>"left", right=>"right", ENDCASE=>" bot "]; ShowDecimal[event.offset," offset "]; ShowString[SELECT event.level FROM red=>" r ", blue=>" b ", ENDCASE=>" x "]; ShowString[IF event.opposite=NIL THEN " lone " ELSE " pair "]; ENDLOOP; Return[]; ShowDecimal[rect.nw, " nw "]; ShowDecimal[rect.sw, " sw "]; ShowDecimal[rect.ne, " ne "]; ShowDecimal[rect.se, " se "]; ShowDecimal[rect.en, " en "]; ShowDecimal[rect.wn, " wn "]; ShowDecimal[rect.es, " es "]; ShowDecimal[rect.ws, " ws "]; Return[]; ShowDecimal[rect.levelers.n, "levelersN "]; ShowDecimal[rect.levelers.s, " levelersS "]; ShowDecimal[rect.levelers.e, " levelersE "]; ShowDecimal[rect.levelers.w, " levelersW "]; Return[]; ShowDecimal[rect.margins.n, "marginsN "]; ShowDecimal[rect.margins.s, " marginsS "]; ShowDecimal[rect.margins.e, " marginsE "]; ShowDecimal[rect.margins.w, " marginsW "]; Return[]; ShowDecimal[rect.used, "used "]; ShowDecimal[rect.avail, " avail "]; ShowDecimal[rect.usedCircuit, " usedCircuit "]; END; ShowSilicon:PROCEDURE=BEGIN offset:CARDINAL_0; oldLine:STRING_[200]; newLine:STRING_[200]; printLine:STRING_[80]; IF chipmonk THEN RETURN[]; PrintSilicon[]; FOR section:INTEGER IN [0..2) DO y:Lambda_problem.chipSize.y; seen:INTEGER_0; oldLine[0]_'M;--make it change! Return[]; Return[]; -- FindSpeedx[]; FindSpeedy[]; DO y_y-1; IF y<0 THEN EXIT; FOR kkk:INTEGER IN [0..LENGTH[speedy1^]) DO IF y=speedy1[kkk] THEN {y_y-speedy2[kkk]; EXIT}; ENDLOOP; MakeNewLine[newLine,y]; seen_IF SameString[newLine,oldLine] THEN seen+1 ELSE 0; IF seen=0 THEN BEGIN s:CARDINAL_newLine.length-offset; IF newLine.length<=offset THEN {IF section=0 THEN Error ELSE RETURN}; printLine.length_MIN[80,s]; FOR j:CARDINAL IN [0..80) DO printLine[j]_newLine[offset+j]; ENDLOOP; END; IF seen<6 THEN BEGIN Return[]; ShowString[printLine]; END; {temp:STRING_oldLine; oldLine_newLine; newLine_temp}; ENDLOOP; offset_offset+80; ENDLOOP; END; PrintSilicon:PROCEDURE=BEGIN ShowLabel["SILICON"]; FOR sl:SiliconListPtr_layout,sl.t UNTIL sl=NIL DO Return[]; ShowWire[sl.h]; ENDLOOP; END; FindSpeedy:PROCEDURE=BEGIN run:INTEGER_0; speedy1^_ALL[0]; speedy2^_ALL[0]; FOR yy:Lambda IN [0..problem.chipSize.y) DO hit:BOOLEAN_yy>problem.chipSize.y-6; FOR cl:CellListPtr_problem.cells,cl.t UNTIL cl=NIL DO c:CellPtr=cl.h; IF c.pos.y-yy IN [0..6) OR c.pos.y+c.sizeL.y-yy IN [0..6) THEN hit_TRUE; ENDLOOP; FOR sl:SiliconListPtr_layout,sl.t UNTIL sl=NIL DO s:SiliconPtr=sl.h; IF s.pos.y-yy IN [0..6) OR s.pos2.y-yy IN [0..6) THEN hit_TRUE; ENDLOOP; IF hit AND run#0 THEN BEGIN start:INTEGER_yy-1; FOR kkk:INTEGER IN [0..LENGTH[speedy1^]) DO IF run>speedy2[kkk] THEN BEGIN {t:INTEGER_speedy2[kkk]; speedy2[kkk]_run; run_t}; {t:INTEGER_speedy1[kkk]; speedy1[kkk]_start; start_t}; END; ENDLOOP; END; run_IF hit THEN 0 ELSE run+1; ENDLOOP; END; MakeNewLine:PROCEDURE[s:STRING,y:Lambda]=BEGIN i:CARDINAL_0; run:INTEGER_0; x:Lambda_-1; topy:Lambda=problem.chipSize.y-1; Clear[s]; IF y=topy THEN {speed1^_ALL[0]; speed2^_ALL[0]}; DO hit:BOOLEAN_FALSE; what:CHARACTER_' ; x_x+1; IF x>=problem.chipSize.x THEN EXIT; FOR kkk:INTEGER IN [0..LENGTH[speed1^]) DO IF x=speed1[kkk] THEN {x_x+speed2[kkk]; EXIT}; ENDLOOP; FOR cl:CellListPtr_problem.cells,cl.t UNTIL cl=NIL DO cell:CellPtr=cl.h; IF x IN [cell.pos.x..cell.pos.x+cell.sizeL.x) AND y IN [cell.pos.y..cell.pos.y+cell.sizeL.y) THEN what_'C; IF x-cell.pos.x IN [0..6) OR x-cell.pos.x-cell.sizeL.x IN [0..6) THEN hit_TRUE; ENDLOOP; FOR sl:SiliconListPtr_layout,sl.t UNTIL sl=NIL DO silicon:SiliconPtr=sl.h; IF x-silicon.pos.x IN [0..6) OR x-silicon.pos2.x IN [0..6) THEN hit_TRUE; IF x IN [silicon.pos.x..silicon.pos2.x) AND y IN [silicon.pos.y..silicon.pos2.y) THEN what_IF silicon.level=both THEN 'x ELSE SELECT what FROM ' =>IF silicon.level=red THEN 'r ELSE 'b, 'r=>IF silicon.level=red THEN 'r ELSE 'o, 'b=>IF silicon.level=red THEN 'o ELSE 'b, 'o=>'o, 'x=>'x, 'C=>'C, ENDCASE=>ERROR; ENDLOOP; IF hit THEN BEGIN s[i]_what; s.length_i_i+1; IF i>=s.maxlength THEN RETURN; IF y=topy AND run#0 THEN BEGIN start:INTEGER_x-run; FOR kkk:INTEGER IN [0..LENGTH[speed1^]) DO IF run>speed2[kkk] THEN BEGIN {t:INTEGER_speed2[kkk]; speed2[kkk]_run; run_t}; {t:INTEGER_speed1[kkk]; speed1[kkk]_start; start_t}; END; ENDLOOP; END; run_0; END ELSE run_run+1; ENDLOOP; END; -- Utilities Rot:PROCEDURE[rect:RectanglePtr,run:RunNo] RETURNS[z:Lambda]=BEGIN del:Lambda=Across[run]; z_IF rect.orient=hor THEN rect.pos.y+del ELSE rect.pos.x+rect.sizeL.x-del; END; Across:PROCEDURE[run:RunNo] RETURNS[Lambda]=BEGIN IF run=bigRun THEN RETURN[topL]; IF run=-1 THEN RETURN[0]; RETURN[7*run+spaceB]; END; MakeBlueWire:PUBLIC PROCEDURE[hor:BOOLEAN,x,y,l:Lambda]=BEGIN IF l=0 THEN RETURN ELSE BEGIN s:SiliconPtr_AddSilicon[]; IF l<0 THEN {IF hor THEN x_x+l ELSE y_y+l; l_-l}; s.level_blue; s.pos_[x,y]; s.pos2_IF hor THEN [x+l,y+3] ELSE [x+3,y+l]; END; END; MakeRedWire:PUBLIC PROCEDURE[hor:BOOLEAN,x,y,l:Lambda]=BEGIN IF l=0 THEN RETURN ELSE BEGIN s:SiliconPtr_AddSilicon[]; IF l<0 THEN {IF hor THEN x_x+l ELSE y_y+l; l_-l}; s.level_red; s.pos_[x,y]; s.pos2_IF hor THEN [x+l,y+2] ELSE [x+2,y+l]; END; END; MakeContact:PUBLIC PROCEDURE[x,y:Lambda]=BEGIN s:SiliconPtr_AddSilicon[]; s.level_both; s.pos_[x,y]; s.pos2_[x+4,y+4]; END; AddSilicon:PROCEDURE RETURNS[s:SiliconPtr]=BEGIN list:SiliconListPtr_AllocateList[]; s_AllocateSilicon[]; list^_[s,layout]; layout_list; END; --known Join Types: -- 1 = straight through -- 2 = up 2 then jog right 6 then proceed up -- 3 = up 2 then jog left 4 then proceed up END. FindJoinType:PROCEDURE[rect:RectanglePtr,conn:ConnPtr,side:Side] RETURNS[JoinType] =BEGIN SELECT side FROM n,w=>IF conn.end#bigRun THEN Error; s,e=>IF conn.start#-1 THEN Error; ENDCASE; IF conn.offset NOT IN [-1..1] THEN {Error; RETURN[0]}; RETURN[SELECT conn.offset FROM -1=>3, 0=>1, 1=>2, ENDCASE=>ERROR]; END;