--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;