-- wiresCreate3.mesa

DIRECTORY SystemDefs:FROM"SystemDefs",
AltoFileDefs:FROM"AltoFileDefs",
DirectoryDefs:FROM"DirectoryDefs",
DisplayDefs:FROM"DisplayDefs",
SegmentDefs:FROM"SegmentDefs",
StreamDefs:FROM"StreamDefs",
StringDefs:FROM"StringDefs",
WiresDefs:FROM"WiresDefs",
IODefs:FROM"IODefs";
WiresCreate:PROGRAM
IMPORTS SystemDefs, IODefs, StreamDefs,
DirectoryDefs,StringDefs,WiresDefs
EXPORTS WiresDefs =BEGIN OPEN WiresDefs;

Error:SIGNAL=CODE;
nullLoc: Location=[NULL,127,127];

EnumerateCircuit:PROCEDURE[call:OnI]=
BEGIN i:INTEGER; FOR i IN [0..topCircuit) DO call[i]; ENDLOOP; END;


--//////////////WIRE LIST Stuff///////////////

wireListArray:TYPE=ARRAY [0..maxWireNo] OF Wire;
wireList:POINTER TO wireListArray←NIL;
maxWireNo:INTEGER=3*maxSide*maxSide;
topWire:INTEGER;

EnumerateWires:PUBLIC PROCEDURE[call:PROCEDURE[INTEGER,WirePtr]]=BEGIN
i:INTEGER; FOR i IN [0..topWire) DO call[i,@wireList[i]]; ENDLOOP; END;

WireLength:PUBLIC PROCEDURE[i,j:Location] RETURNS[INTEGER]=BEGIN
RETURN[ABS[i.i-j.i]+ABS[i.j-j.j]]; END;

MakeWireList:PUBLIC PROCEDURE[print:BOOLEAN]= BEGIN
MakeTrack[]; -- chain the transistors
topWire←0;
EnumerateCircuit[WireListOneCircuit];
SortWireList[];
IF print THEN PrintWireList;
END;

AddToWireList:PROCEDURE[w:Wire]=BEGIN
wireList[topWire]←w;
topWire←topWire+1;
IF topWire>maxWireNo THEN Error;
END;

PrintWireList:PUBLIC PROCEDURE=BEGIN EnumerateWires[PrintWireListEntry]; END;

PrintWireListEntry:PROCEDURE[i: INTEGER, w:WirePtr]=BEGIN OPEN IODefs;
WriteNumber[i,[10,FALSE,TRUE,4]];
WriteString[" Circuit"]; WriteNumber[w.circuit,[10,FALSE,TRUE,3]];
WriteString[" length"]; WriteNumber[w.l,[10,FALSE,TRUE,3]];
WriteString[" from "]; WriteLocation[w.a];
WriteString[" to "]; WriteLocation[w.b];
WriteChar[CR];
END;

colorStrings:ARRAY Color OF STRING=["none "," red ","green","blue ","yel. "];

WriteLocation:PROCEDURE[l:Location]=BEGIN OPEN IODefs;
WriteNumber[l.i,[10,FALSE,TRUE,2]];
WriteChar[’,];
WriteNumber[l.j,[10,FALSE,TRUE,2]];
WriteString[SELECT l.contact FROM
chanA=>" chanA",
gate=>" gate",
chanB=>" chanB",
ENDCASE=>ERROR];
END;

thisW:INTEGER;

WireListOneCircuit:PROCEDURE[i:INTEGER]=BEGIN
-- IF i=vdd OR i=gnd THEN RETURN;
thisW←i;
InitTemp[];
EnumerateTrack[i,AddToTemp];
EnumerateTemp[InitSep];
EnumerateTemp[FindAndUseNextSmallestTemp];
END;

SortWireList:PROCEDURE=BEGIN i,j:INTEGER;
FOR i IN [0..topWire) DO FOR j IN (i..topWire) DO
IF ShorterWire[j,i] THEN BEGIN
temp:Wire←wireList[i]; wireList[i]←wireList[j]; wireList[j]←temp;
END;
ENDLOOP; ENDLOOP;
END;

ShorterWire:PROCEDURE[i,j:INTEGER] RETURNS[BOOLEAN]=BEGIN
wi:WirePtr←@wireList[i];
wj:WirePtr←@wireList[j];
nonGreeni:BOOLEAN←wi.a.contact=gate OR wi.b.contact=gate;
nonGreenj:BOOLEAN←wj.a.contact=gate OR wj.b.contact=gate;
circuiti:INTEGER←SELECT wi.circuit FROM gnd=>3,vdd=>2,ENDCASE=>1;
circuitj:INTEGER←SELECT wj.circuit FROM gnd=>3,vdd=>2,ENDCASE=>1;
RETURN[IF circuiti#circuitj THEN circuiti<circuitj
ELSE IF nonGreeni#nonGreenj THEN nonGreenj
ELSE wi.l<wj.l];
END;

--///// END WIRELIST STUFF////
--///// START TEMP STUFF /////

wireTempArray:TYPE=ARRAY [0..maxTemp] OF Location;
wireSepArray:TYPE=ARRAY [0..maxTemp] OF INTEGER;

maxTemp:INTEGER=maxSide*maxSide/2 +1;
topTemp:INTEGER;
wireTemp:POINTER TO wireTempArray←NIL;
wireSep:POINTER TO wireSepArray←NIL;

EnumerateTemp:PROCEDURE[call:OnI]=
BEGIN k:INTEGER; FOR k IN [0..topTemp) DO call[k]; ENDLOOP; END;

InitTemp:PROCEDURE=BEGIN topTemp←0; END;

InitSep:OnI=BEGIN wireSep[i]←i; END;

AddToTemp:PROCEDURE[l:Location]=BEGIN
wireTemp[topTemp]←l; topTemp←topTemp+1; IF topTemp>maxTemp THEN Error;
END;

FindAndUseNextSmallestTemp:PROCEDURE[i:INTEGER]=BEGIN
bestj:INTEGER; best:INTEGER←10000; k:INTEGER=i;

FindClosest:OnI=BEGIN
l:INTEGER←WireLength[wireTemp[i],wireTemp[k]];
IF wireSep[k]#wireSep[i] AND l<best THEN BEGIN best←l; bestj←i; END;
END;

WindSep:OnI=BEGIN IF wireSep[i]=wireSep[k] THEN wireSep[i]←wireSep[bestj];
END;

EnumerateTemp[FindClosest];
IF best=10000 THEN RETURN;
AddToWireList[[a:wireTemp[i],
b:wireTemp[bestj],c:none,l:best,circuit:thisW]];
EnumerateTemp[WindSep];
END;

--////// END TEMP STUFF////

--//////////////CONTROL///////////////

AllocateStuffForCreate:PUBLIC PROCEDURE=BEGIN OPEN SystemDefs;
wireList←AllocateSegment[SIZE[wireListArray]];
grid←AllocateSegment[SIZE[gridType]];
track←AllocateSegment[SIZE[trackType]];
circuits←AllocateSegment[SIZE[circuitsType]];
wireTemp←AllocateSegment[SIZE[wireTempArray]];
wireSep←AllocateSegment[SIZE[wireSepArray]];
END;

RecoverStuffInCreate:PUBLIC PROCEDURE=BEGIN OPEN SystemDefs;
FreeSegment[grid];
FreeSegment[track];
FreeSegment[circuits];
FreeSegment[wireTemp];
FreeSegment[wireSep];
grid←track←circuits←wireTemp←wireSep←NIL;
END;

--//////////////GRID///////////////

side:PUBLIC Loc;
printGrid:POINTER TO gridType;
grid:PUBLIC POINTER TO gridType←NIL;

EnumerateGrid:PUBLIC PROCEDURE[call:PROCEDURE[i,j:INTEGER]]=BEGIN i,j:INTEGER;
FOR i IN (0..side] DO FOR j IN (0..side] DO call[i,j]; ENDLOOP; ENDLOOP;
END;

EnumerateGridPlusOne:PUBLIC PROCEDURE[call:PROCEDURE[i,j:INTEGER]]=BEGIN i,j:INTEGER;
FOR i IN [0..side+1) DO FOR j IN [0..side+1) DO call[i,j]; ENDLOOP; ENDLOOP;
END;

EnumerateGridPlusTwo:PUBLIC PROCEDURE[call:PROCEDURE[i,j:INTEGER]]=BEGIN i,j:INTEGER;
FOR i IN [0..side+1] DO FOR j IN [0..side+1] DO call[i,j]; ENDLOOP; ENDLOOP;
END;

ClearGrid:PUBLIC PROCEDURE[i,j:INTEGER]=BEGIN grid[i][j]←nullTransistor; END;

EnumerateSide:PUBLIC PROCEDURE[call:PROCEDURE[INTEGER]]=BEGIN
i:INTEGER; FOR i IN (0..side] DO call[i]; ENDLOOP; END;

EnumerateSidePlusOne:PUBLIC PROCEDURE[call:PROCEDURE[INTEGER]]=BEGIN
i:INTEGER; FOR i IN [0..side] DO call[i]; ENDLOOP; END;

EnumerateSidePlusTwo:PUBLIC PROCEDURE[call:PROCEDURE[INTEGER]]=BEGIN
i:INTEGER; FOR i IN [0..side+1] DO call[i]; ENDLOOP; END;


--//////////////TRACK///////////////

--the purpose of track is to efficiently find all the transistors in a circuit
--the track operations are:
--Make Track, which builds the data structures
--EnumerateTrack, which calls you back with each transistor participating
-- in the specified circuit
--Valid Circuit, which returns true if there is some transistor this circuit

circuitsType:TYPE=ARRAY [0..topCircuit+5) OF Location;
circuits:POINTER TO circuitsType←NIL;

LTriple:TYPE=RECORD[a,b,c:Location];
trackType:TYPE=ARRAY [0..maxSide) OF ARRAY [0..maxSide) OF LTriple;
track:POINTER TO trackType←NIL;

MakeTrack:PROCEDURE=BEGIN
EnumerateCircuit[ClearCircuit];
EnumerateGrid[ClearTrack];
EnumerateGrid[BuildTrack];
END;

EnumerateTrack:PROCEDURE[i:INTEGER,Call:PROCEDURE[Location]]=BEGIN
l:Location;
FOR l←circuits[i],SELECT l.contact FROM
chanA=>track[l.i][l.j].a ,
gate=>track[l.i][l.j].b,
chanB=>track[l.i][l.j].c,
ENDCASE => ERROR
UNTIL l=nullLoc DO Call[l]; ENDLOOP;
END;

ValidCircuit:PROCEDURE[i:INTEGER] RETURNS[BOOLEAN]=
BEGIN RETURN[circuits[i]#nullLoc];END;

ClearCircuit:PROCEDURE[i:INTEGER]=BEGIN circuits[i]←nullLoc; END;

ClearTrack:PROCEDURE[i,j:INTEGER]=
BEGIN track[i][j]←[nullLoc,nullLoc,nullLoc]; END;

BuildTrack:PROCEDURE[i,j:INTEGER]=BEGIN
s,t,w:Circuit;
[s,t,w]←grid[i][j];
IF s ~IN [0..topCircuit]
OR t ~IN [0..topCircuit]
OR w ~IN [0..topCircuit] THEN Error;
track[i][j]←[circuits[s],circuits[t],circuits[w]];
IF t=s THEN track[i][j].b←[chanA,i,j] -- Handle pullups
ELSE IF t=w THEN track[i][j].b←[chanB,i,j];
circuits[s]←[chanA,i,j];
circuits[w]←[chanB,i,j];
circuits[t]←[gate,i,j]; -- If s=t or w=t this will override. It’s OK.
END;

--//////////////INPUT STUFF///////////////


GetInput:PUBLIC PROCEDURE[print:BOOLEAN,circuitName: STRING]=BEGIN
OPEN AltoFileDefs,IODefs,DirectoryDefs,StreamDefs,
SegmentDefs,StringDefs;
kbdStream,otherStream,currentStream: StreamHandle;
pInFileFP: POINTER TO FP;
inFileFP: FP;
fileNameValid,readFromKbd: BOOLEAN;
inFileName: STRING ← [40];
inputLine: STRING ← [80];
tempString: STRING←[10];
inputTail: SubString;

ChompDecimal: PROCEDURE[src: SubString] RETURNS[INTEGER]=BEGIN
OPEN StringDefs;
i,j,sign,wall: INTEGER;
wall ←src.offset+src.length-1; -- mark the end of line
i ← src.offset;
j ← 0;
WHILE IF i<= wall THEN src.base.text[i]=’ ELSE FALSE
DO i ← i+1; ENDLOOP; -- skip blanks
IF src.base.text[i]=’- THEN BEGIN sign←-1; i←i+1 END ELSE sign←1;
IF src.base.text[i] NOT IN [’0..’9] THEN Error;
WHILE IF i<= wall THEN src.base.text[i] IN [’0..’9] ELSE FALSE
DO
j ← 10*j+(src.base.text[i]-’0);
i ← i + 1;
ENDLOOP;
src.length←src.length-(i-src.offset);
src.offset←i;
RETURN[sign*j];
END;

ChompID: PROCEDURE[src: SubString, dest:STRING]=BEGIN
OPEN StringDefs;
i,wall: INTEGER;
temp: SubString;
tempD: SubStringDescriptor;
temp ← @tempD;
tempD.base←src.base;
dest.length←0;
wall ←src.offset+src.length-1; -- mark the end of line
i ← src.offset;
WHILE IF i<= wall THEN src.base.text[i]=’ ELSE FALSE
DO i ← i+1; ENDLOOP; -- skip initial blanks
tempD.offset←i;
tempD.length←0;
WHILE IF i<= wall THEN src.base.text[i]#’ ELSE FALSE
DO
i ← i + 1;
tempD.length←tempD.length+1;
ENDLOOP;
AppendSubString[dest,temp];
src.length←src.length-(i-src.offset);
src.offset←i;
END;


ParseTransistor: PRIVATE PROCEDURE RETURNS[BOOLEAN]=BEGIN
OPEN IODefs, StreamDefs, StringDefs;
a,b,c: INTEGER;
i,j: INTEGER;

IF (IF currentStream#kbdStream THEN TRUE ELSE
~currentStream.endof[currentStream]) -- blame kbdStream lossage
THEN BEGIN -- parse a line --
ReadLine[inputLine];
inputTail↑ ←SubStringDescriptor[inputLine,0,inputLine.length];
i ← ChompDecimal[inputTail];
IF i < 0 THEN RETURN[FALSE];
j ← ChompDecimal[inputTail];
IF (i NOT IN [1..side]) OR (j NOT IN [1..side]) THEN Error;
ChompID[inputTail,tempString];
a ← CPTI[tempString];
ChompID[inputTail,tempString];
b ← CPTI[tempString];
ChompID[inputTail,tempString];
c ← CPTI[tempString];
grid[i][j]←[a,b,c];
END ELSE RETURN[FALSE];
RETURN[TRUE];
END; -- of ParseTransistor --

-- begin body of GetInput
pInFileFP←@inFileFP;
fileNameValid ← readFromKbd ← FALSE;
UNTIL fileNameValid DO
WriteString["Enter the Name of the File for Input:"];
ReadID[inFileName];
WriteChar[CR];
IF inFileName.length=0 THEN
fileNameValid ← readFromKbd ← TRUE
ELSE fileNameValid←DirectoryLookup[pInFileFP,inFileName,FALSE];
ENDLOOP;
circuitName.length←0;
WHILE circuitName.length<20 AND
inFileName.text[circuitName.length]#’. DO
circuitName.text[circuitName.length]←inFileName.text[circuitName.length];
circuitName.length←circuitName.length+1;
ENDLOOP;
currentStream ← kbdStream ← GetInputStream[];
IF readFromKbd THEN
WriteLine["Input from Keyboard Requested. Proceed."]
ELSE BEGIN
currentStream ← otherStream ←NewByteStream[inFileName,Read];
SetInputStream[otherStream];
END;
-- Get first line to decide on the size --
ReadLine[inputLine];
inputTail↑ ←[inputLine,0,inputLine.length];
side ← ChompDecimal[inputTail];
IF side>maxSide THEN BEGIN
IODefs.WriteLine["ABORT!! side>maxSide. You have to recompile."];
ERROR;
END;
InitAtoms[];
EnumerateGrid[ClearGrid];

WHILE ParseTransistor[] DO NULL; ENDLOOP;

IF ~readFromKbd THEN
BEGIN
SetInputStream[kbdStream];
otherStream.destroy[otherStream];
END;
IF print THEN PrintG[];
END;


--///////////////PRINTING//////////////

PrintG:PUBLIC PROCEDURE=BEGIN OPEN IODefs,StreamDefs;
i,j: INTEGER;
output: StreamHandle;
output←GetOutputStream[];
printGrid←grid;
IODefs.WriteChar[CR];
-- Write a Header Line
IODefs.WriteString["j(y)\i(x)"];
FOR i IN (0..side] DO IODefs.OutNumber[output,i,
NumberFormat[10,FALSE,FALSE,11] ]; ENDLOOP;
IODefs.WriteChar[CR];
IODefs.WriteChar[CR];
-- Write out the Grid.
FOR j DECREASING IN (0..side] DO -- handle the y’s
IODefs.OutNumber[output,j,NumberFormat[10,FALSE,FALSE,11] ];
FOR i IN (0..side] DO -- x coordinate
PrintGrid[i,j];
ENDLOOP;
IODefs.WriteChar[CR];
ENDLOOP;
END;

PrintGSection:PUBLIC PROCEDURE=BEGIN
printGrid←grid;
IODefs.WriteChar[CR];
EnumerateGrid[PrintGridSection];
END;

PrintGrid:PROCEDURE[i,j:INTEGER]=BEGIN OPEN IODefs;
WriteChar[’ ];
WriteId[printGrid[i][j].a];
WriteId[printGrid[i][j].b];
WriteId[printGrid[i][j].c];
WriteChar[’ ];
END;

PrintGridSection:PROCEDURE[i,j:INTEGER]=BEGIN OPEN IODefs;
x:INTEGER;
IF j=0 THEN WriteChar[CR];
x←MAX[FindSectionId[printGrid[i][j].a],
FindSectionId[printGrid[i][j].b],
FindSectionId[printGrid[i][j].c]];
WriteChar[SELECT x FROM -1=>’x,0=>’0,1=>’1,2=>’2,3=>’3,4=>’4,
5=>’5,6=>’6,7=>’7,8=>’8,ENDCASE=>’9];
END;

WriteId:PROCEDURE[a:INTEGER]=BEGIN
IF a=nullCircuit THEN IODefs.WriteString[" "]
ELSE BEGIN
IODefs.WriteChar[’ ];
IODefs.WriteChar[atoms[a].a];
IODefs.WriteChar[atoms[a].b];
END;
END;

FindSectionId:PROCEDURE[a:INTEGER] RETURNS[INTEGER]=BEGIN
IF a=gnd THEN RETURN[-1];
RETURN[SELECT atoms[a].a FROM
’0,’ =>0, ’1=>1, ’2=>2, ’3=>3, ’4=>4, ’5=>5, ’6=>6, ’7=>7, ’8=>8,
ENDCASE=>-1];
END;

--/////////////ATOMS//////////////

Id:TYPE=RECORD[a,b:CHARACTER];
atoms:ARRAY[0..maxAtom+3] OF Id;
maxAtom:INTEGER=200;
topAtom,vdd,gnd:INTEGER;
tempString:STRING←[6];


InitAtoms:PROCEDURE=BEGIN
gd: STRING="gd";
vd: STRING="vd";
topAtom←0;
gnd←CPTI["gd"];
vdd←CPTI["vd"];
END;

CPTI:PROCEDURE[inStr:STRING] RETURNS[b:INTEGER]=BEGIN
id: Id;
i:INTEGER;
IF inStr.length=1 THEN id ←[’ ,inStr.text[0]]
ELSE id ←[inStr.text[0],inStr.text[1]];
FOR i IN [0..topAtom) DO IF id=atoms[i] THEN RETURN[i]; ENDLOOP;
atoms[topAtom]←id;
topAtom←topAtom+1;
IF topAtom>maxAtom THEN Error;
RETURN[topAtom-1];
END;

END..