-- I/O module of silicon (pretty picture) program
-- last modified by Dillon, April 11, 1984 12:11 AM
-- to allow rdErfLine to use pCifScale<2 correctly
-- last modified by McCreight, December 20, 1983 2:34 PM
-- to read in multiple implant levels
-- modified by Petit, September 20, 1981
DIRECTORY
InlineDefs,
StreamDefs,
SystemDefs,
IODefs,
AltoDefs,
DirectoryDefs,
AltoFileDefs,
StringDefs,
ChipUserInt,
ppoutdefs,
ppdddefs,ppddefs,
ppdefs;
ppio: PROGRAM
IMPORTS
ChipUserInt, ppdefs, ppddefs, ppdddefs,ppoutdefs, InlineDefs,
StreamDefs, StringDefs, DirectoryDefs
EXPORTS ppdefs, ppddefs =
BEGIN
OPEN ppdefs, ppddefs, ppdddefs,ppoutdefs, InlineDefs, StreamDefs, IODefs, StringDefs,
DirectoryDefs;
fp: AltoFileDefs.FP;
-- press command byte defs:
fontset: CARDINAL = 160B;
setx: CARDINAL = 356B;
sety: CARDINAL = 357B;
showchar: CARDINAL = 360B;
showcharim: CARDINAL = 363B;
showrect: CARDINAL = 376B;
setBrt: CARDINAL = 370B;
setHue: CARDINAL = 371B;
setSat: CARDINAL = 372B;
currentColor: level;
hardCopyScaleNumber: INTEGER = 42;
hScale: INTEGER;
hBrttab: ARRAY level OF CARDINAL ← [30, 255, 255, 255, 235, 255, 190, 255
,180,255,255,180,255,220,255,255];
hHuetab: ARRAY level OF CARDINAL ← [10, 70, 215, 130, 40, 220, 10, 220
,10,70,255,15,255,5,5,255];
hSattab: ARRAY level OF CARDINAL ← [0, 190, 180, 190, 225, 220, 112, 120
,255,190,255,200,255,80,255,255];
layNam: ARRAY level OF CHARACTER ← ['C, 'D, 'P, 'M, 'I, 'G, 'B, 'X,
'O, 'Q, 'X, 'S, 'X, 'T, 'X, 'X];
byteCnt, saveByte: CARDINAL;
hscale: PROCEDURE [x, y: INTEGER] RETURNS [INTEGER, INTEGER];
-- dummy font name:
fontName: ARRAY [1..20] OF CARDINAL ← [
9, 110B, 105B, 114B, 126B, 105B, 124B, 111B, 103B, 101B, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0];
contLevel: ARRAY [1..contTypALen] OF level =
[dif, pol, dif,dif, met2, pdif,nwelCont,dif,pol,pdif,dif,dif]; -- for versions<6
inObject: PROCEDURE [version: CARDINAL] RETURNS [ob: LONG POINTER TO object] =
BEGIN
j, k: CARDINAL;
w, l, we, le,ii,sur: INTEGER;
lev:level;
sur←6;
j ← inWord[];
SELECT j FROM
1 =>
BEGIN
k ← inWord[]; -- get unique cell id
ob ← cellNameA[k].p.anotherme[cellNameA[k]]
END;
2 =>
BEGIN
impl: DepletionStrength ← enhancement;
w ← inWord[];
l ← inWord[];
k ← inWord[];
IF version>4 AND BITAND[k,10000B]#0
THEN sur ← inWord[];-- if pdif, get surround
IF BITAND[k,20000B]#0 THEN j ← inWord[];-- if angle, get angle ext.
IF BITAND[k, 100000B]#0 THEN
BEGIN
IF version>7 THEN impl ← inWord[] ELSE impl ← LAST[DepletionStrength];
END;
we ← BITAND[BITSHIFT[k, -6], 77B];
le ← BITAND[k, 77B];
lev ← IF BITAND[k,10000B]#0 THEN pdif ELSE dif;
ob ←
SELECT TRUE FROM
BITAND[k, 40000B] # 0 => makePullup[w, l,we,le, lev],
BITAND[k,20000B]#0 =>
makeAngleXstr[w, l, impl,we,le,j, lev],
ENDCASE => makeXstr[w, l, impl,we,le,lev];
END;
3 =>
BEGIN
j ← inWord[]; -- get contact type
k ← BITAND[j, 37B]; -- get contact type
l ← BITSHIFT[j, -8];
lev ← IF version>5 THEN inWord[] ELSE contLevel[k];
IF version>4 THEN sur←inWord[];
SELECT contTypA[k] FROM
mPol => ob ← makePolycon[l];
mDif => ob ← makeDifcon[l, lev];
difShort => ob ← makeDifShortCont[lev];
butt => ob ← makeButcon[lev];
burr => BEGIN
w←inWord[];
k←inWord[];
j←BITSHIFT[k,-8];
ob ← makeBuCont[w,l,j,BITAND[k,377B], lev];
END;
mm2 => ob ← makeMmCont[l,0,0];
ENDCASE => ERROR;
END;
4 =>
BEGIN
w ← inWord[];
l ← inWord[];
lev ← inWord[];
IF version>4 AND lev=pdif THEN sur←inWord[];
ob ← makeWire[l, w, lev,sur];
END;
5 =>
BEGIN
w ← inWord[];
l ← inWord[];
lev ← inWord[];
ob ← makeRect[w, l, lev];
END;
6 => BEGIN ob ← makeText[inString[]]; END;
7 =>
BEGIN
w ← inWord[];
l ← inWord[];
lev ← inWord[];--level
j ← inWord[];--cnt
we ← inWord[];--spacing
le ← inWord[];--top incr
ii ← inWord[];--bot incr
ob ← makeBus[l, w, lev,j,we,le,ii];
END;
8 =>
BEGIN
obb: obPtr = inObject[version];
w ← inWord[];
l ← inWord[];
we ← inWord[];
le ← inWord[];
ii ← inWord[];--cnt
j ← inWord[];--idx
ob ← makeRep[obb, w, l, we, le, ii, j];
END;
ENDCASE => ob ← NIL;
END;
inList: PROCEDURE [ver: CARDINAL, lp: listPtr ← NIL]
RETURNS [listPtr] =
BEGIN
i, j, k, l: CARDINAL;
tail: listPtr;
lp ← NIL;
i ← inWord[];
FOR j IN [0..i) DO
tp: listPtr ← alocList[];
tp.nxt ← NIL;
tp.lx ← inWord[];
tp.ly ← inWord[];
tp.idx ← inWord[];
tp.ridx ← BITXOR[tp.idx, 1];
tp.ob ← inObject[ver];
tp.props ← NIL;
IF ver > 3 THEN
BEGIN
k ← inWord[];
FOR l IN [0..k) DO
inProp[tp];
ENDLOOP;
END;
IF tp.ob # NIL THEN -- link it in, in FIFO order
{IF lp=NIL THEN lp ← tp ELSE tail.nxt ← tp; tail ← tp};
ENDLOOP;
RETURN[lp];
END;
instanceName, signalName: Atom;
inProp: PROCEDURE [lp: listPtr] =
BEGIN
i: CARDINAL;
i ← inWord[];
SELECT i FROM
1 =>
BEGIN
value: STRING = inString[];
attribute: Atom = SELECT lp.ob.otyp FROM
rect, wire => signalName,
ENDCASE => instanceName;
putProp[lp: lp, attribute: attribute, value: MakeAtom[value]];
FreeString[value];
END;
2 =>
BEGIN
attribute: Atom = inAtom[];
value: Atom = inAtom[];
putProp[lp: lp, attribute: attribute, value: value];
END;
ENDCASE => NULL;
END;
inWord: PROC RETURNS [UNSPECIFIED]; -- variable
readAll: PUBLIC PROCEDURE [get: PROC RETURNS[UNSPECIFIED]] = BEGIN
ml: listPtr;
cl: cListPtr;
[masterList: ml, cellList: cl, cellStack: cellStack] ← readChip[get
! ChipUserInt.Punt => GOTO NoChange];
flushDel[unDelPnt];
unDelPnt ← NIL;
unDelGrpCnt ← unDelItemCnt ← 0;
FOR lpp: LONG POINTER TO listPtr ← @masterList, @lpp.nxt DO
IF lpp↑=NIL THEN {lpp↑ ← ml; EXIT};
ENDLOOP; -- append ml to masterList
FOR clp: LONG POINTER TO cListPtr ← @cellList, @clp.nxt DO
IF clp↑=NIL THEN {clp↑ ← cl; EXIT};
ENDLOOP; -- append cl to cellList
pushLevel ← 0;
FOR cs: cellSEPtr ← cellStack, cs.nxt WHILE cs#NIL DO
pushLevel ← pushLevel+1;
ENDLOOP;
EXITS NoChange => NULL;
END;
readChip: PUBLIC PROCEDURE [get: PROC RETURNS[UNSPECIFIED]]
RETURNS[masterList: listPtr, cellList: cListPtr, cellStack: cellSEPtr] =
BEGIN
i, j, ver, depth: CARDINAL;
ss: STRING;
inWord ← get;
instanceName ← atomTable[1] ← MakeAtom["Instance name"];
signalName ← atomTable[2] ← MakeAtom["Signal name"];
cellList ← NIL; -- local variables
cellStack ← NIL;
i ← inWord[]; -- read code word
IF i#codeWordForDataFile AND
NOT ChipUserInt.HeSaysYes["This really doesn't look like a valid .chip file."L,
"Shall I press on anyway? (I might crash!)"L] THEN SIGNAL ChipUserInt.Punt;
ver ← inWord[]; -- read version #
cCnt ← inWord[]; -- read count of cells
cellNameA ← DESCRIPTOR[
GetSpace[(cCnt + 1)*SIZE[LONG POINTER TO object]], cCnt + 1];
IF ver < 3 THEN ERROR;
FOR i IN [0..cCnt] DO
-- 0 is an illegal cell that can get generated by a bug
-- in the output routines
cellNameA[i] ← makeCell[Lambda, Lambda, 0, NIL];
ENDLOOP;
FOR i IN [1..cCnt] DO
cdp: LONG POINTER TO cell object;
j ← inWord[];
cdp ← cellNameA[j];
ss ← inString[];
cdp.size[0] ← cdp.size[2] ← inWord[];
cdp.size[1] ← inWord[];
cdp.cnt ← inWord[];
cdp.ptr ← inList[ver];
IF ss.length > 0 THEN
BEGIN
cpp: cListPtr ← alocCList[];
cpp.nxt ← cellList;
cellList ← cpp; -- add to existing cellList
cpp.ob ← cdp.p.anotherme[cdp];
cpp.name ← ss;
cdp.returnable ← FALSE;
END;
ENDLOOP;
depth ← IF ver<7 THEN 0 ELSE inWord[];
WHILE depth>0 DO
top: cellSEPtr = inPushedLevel[ver, depth];
top.nxt ← cellStack;
cellStack ← top;
depth ← inWord[];
ENDLOOP;
IF ver>=7 THEN
BEGIN
fileChanges: BOOLEAN = inWord[];
anyChanges ← anyChanges OR fileChanges;
END;
masterList ← inList[ver, NIL];
FOR i IN [1..cCnt] DO cellNameA[i].p.release[cellNameA[i]]; ENDLOOP;
FreeSpace[BASE[cellNameA]];
END;
atomTable: PUBLIC ARRAY [1..atomTableSize] OF Atom;
inAtom: PROC RETURNS [a: Atom] =
BEGIN
i: INTEGER = inWord[];
IF i>0 THEN
BEGIN
s: STRING ← inString[];
a ← MakeAtom[s];
FreeString[s];
IF i<=256 THEN atomTable[i] ← a;
END
ELSE a ← atomTable[-i];
END;
inPoint: PROC RETURNS [p: Point] = {p.x ← inWord[]; p.y ← inWord[]};
inRect: PROC RETURNS [r: Rect] =
{[[r.x1, r.y1]] ← inPoint[]; [[r.x2, r.y2]] ← inPoint[]};
inInt: PROC RETURNS [i: INT] =
BEGIN
ln: LongNumber;
ln.highbits ← inWord[];
ln.lowbits ← inWord[];
i ← ln.li;
END;
inPushedLevel: PROC [ver: CARDINAL, depth: NAT] RETURNS [cs: cellSEPtr] =
BEGIN
changes: BOOLEAN = inWord[];
origSize: Point = inPoint[];
origBB: Rect = inRect[];
dest: cellPtr = LOOPHOLE[inObject[ver]];
lp: listPtr = inList[ver];
instance: listPtr = inPositionInList[ver, lp];
cs ← GetSpace[SIZE[cellSE]];
cs↑ ← [nxt: NIL,
changes: changes,
origSize: origSize,
origBB: origBB,
dest: dest,
lp: lp,
instance: instance,
udg: 0, udi: 0];
cellStack ← cs;
END;
inPositionInList: PROC[ver: CARDINAL, within: listPtr] RETURNS [target: listPtr] =
BEGIN
i: INT ← inInt[];
IF i=0 THEN RETURN[NIL];
FOR lp: listPtr ← within, lp.nxt DO
i ← i-1;
IF i=0 THEN RETURN[lp];
ENDLOOP;
END;
inString: PROCEDURE RETURNS [s: STRING] =
BEGIN
i, j, len: CARDINAL;
flg: BOOLEAN;
j ← inWord[];
len ← BITSHIFT[j, -8];
IF len = 0 THEN BEGIN s ← ""; RETURN; END;
s ← GetString[len];
s.length ← 0;
flg ← TRUE;
FOR i IN [0..len) DO
IF flg THEN AppendChar[s, BITAND[j, 377B]]
ELSE BEGIN j ← inWord[]; AppendChar[s, BITSHIFT[j, -8]]; END;
flg ← NOT flg;
ENDLOOP;
END;
-- ******** hardcopy stuff:
hdcpyHandle: StreamDefs.DiskHandle; -- for hardcopy
ovByteCnt: CARDINAL;
ovLimit: CARDINAL = 10000;
padWds, pagCnt: CARDINAL;
hardDrR: drRecord ← [
[0,0,0,0], [0,0,0,0], hardOutArea, hardOutArea, nullOutl, nulldtxt, 0];
nullOutl: PROCEDURE [a, b, c, d: INTEGER, q: color, p: POINTER TO Rect] =
BEGIN END;
nulldtxt: PROCEDURE [a, b, c, d: INTEGER, s: STRING, p: POINTER TO Rect] =
BEGIN END;
hardOut: PUBLIC PROCEDURE [fn: STRING, lp: LONG POINTER TO list] =
BEGIN
j: CARDINAL;
fullName: STRING ← [30];
dChange ← TRUE;
fullName.length ← 0;
AppendString[fullName, fn];
AppendString[fullName, ".press"];
hdcpyHandle ← NewWordStream[fullName, Write + Append];
byteCnt ← 0;
pagCnt ← 0;
hWout[0]; -- no text, so this ends the DL
ovByteCnt ← byteCnt;
currentColor ← NOcOL; -- make sure first color we output isn't current
hardDrR.r ← [cClipx1, cClipy1, cClipx2, cClipy2];
hardDrR.bigr ← [cClipx1-wellSurround, cClipy1-wellSurround,
cClipx2+wellSurround, cClipy2+wellSurround];
hScale ← cScaleN*hardCopyScaleNumber;
hscale ← IF cScaleD = 1 THEN hscale1 ELSE hscale2;
WHILE lp # NIL DO
lp.ob.p.drawme[lp.idx][lp.ob, lp.lx, lp.ly, @hardDrR]; lp ← lp.nxt; ENDLOOP;
termEnt[];
padWds ← byteCnt MOD 512;
padWds ← 256 - padWds/2;
FOR j IN [0..padWds) DO hWout[0]; ENDLOOP;
pagCnt ← pagCnt + ((byteCnt + 3)/512);
byteCnt ← 0;
hWout[16]; -- dummy font defn -length
hWout[4]; -- font-set, font
hBout[32];
hBout[127];
FOR j IN [1..20] DO hBout[fontName[j]]; ENDLOOP;
hWout[32]; -- face, source
hWout[10]; -- size
hWout[0]; -- rotation
FOR j IN [0..256 - 16) DO hWout[0]; ENDLOOP;
hWout[0]; -- page part
hWout[0]; -- starts at record 0
hWout[pagCnt]; -- length in pages
hWout[padWds]; -- words of padding
hWout[1]; -- font part
hWout[pagCnt]; -- starts at record pagCnt
hWout[1]; -- length in pages
hWout[0]; -- undefined
FOR j IN [0..256 - 8) DO hWout[0]; ENDLOOP;
hWout[27183]; -- code word
hWout[pagCnt + 3]; -- total records
hWout[2]; -- # of parts
hWout[pagCnt + 1]; -- where part dir starts
hWout[1]; -- # of pages in part dir
hWout[177777B]; -- # of parts
hWout[112300B]; -- date
hWout[106745B]; -- date
hWout[1];
hWout[1];
hWout[177777B];
hWout[177777B];
hWout[124B];
FOR j IN [0..115) DO hWout[177777B]; ENDLOOP;
FOR j IN [0..256 - 115 - 13) DO hWout[0]; ENDLOOP;
hdcpyHandle.destroy[hdcpyHandle];
END;
--hscale:PROCEDURE[x,y:INTEGER]RETURNS[INTEGER,INTEGER]=
-- BEGIN
-- RETURN[((cxoff+x)*hScale)/cScaleD,640-((cyoff+y)*hScale)/cScaleD];
-- RETURN[((cxoff+x)*hScale)/cScaleD,((cClipy2-y)*hScale)/cScaleD];
-- END;
hscale1: PROCEDURE [x, y: INTEGER] RETURNS [INTEGER, INTEGER] =
BEGIN
tx, ty: INTEGER;
ty ← cxoff + x;
tx ← cyoff + y;
RETURN[tx*hScale, ty*hScale];
END;
hscale2: PROCEDURE [x, y: INTEGER] RETURNS [INTEGER, INTEGER] =
BEGIN
tx, ty: INTEGER;
ty ← cxoff + x;
tx ← cyoff + y;
RETURN[
(tx/cScaleD)*hScale + ((tx MOD cScaleD)*hScale)/cScaleD,
(ty/cScaleD)*hScale + ((ty MOD cScaleD)*hScale)/cScaleD];
END;
hscaleRect: PROCEDURE [x1, y1, x2, y2: INTEGER]
RETURNS [BOOLEAN, INTEGER, INTEGER, INTEGER, INTEGER] = INLINE
BEGIN
t: INTEGER;
IF x1 > x2 THEN BEGIN t ← x1; x1 ← x2; x2 ← t; END;
IF y1 > y2 THEN BEGIN t ← y1; y1 ← y2; y2 ← t; END;
IF x1 > cClipx2 OR x2 < cClipx1 OR y1 > cClipy2 OR y2 < cClipy1 THEN
RETURN[FALSE, 0, 0, 0, 0];
[x1, y1] ← hscale[MAX[x1, cClipx1], MAX[y1, cClipy1]];
[x2, y2] ← hscale[MIN[x2, cClipx2], MIN[y2, cClipy2]];
RETURN[TRUE, x1, y2, x2, y1];
END;
hardOutArea: PROCEDURE [x1, y1, x2, y2: INTEGER, l: level, p: POINTER TO Rect] =
BEGIN
a, b, c, d: INTEGER;
bb: BOOLEAN;
[bb, a, b, c, d] ← hscaleRect[x1, y1, x2, y2];
IF bb THEN
BEGIN
IF l # currentColor THEN
BEGIN
currentColor ← l;
hBout[setBrt];
hBout[hBrttab[l]];
hBout[setHue];
hBout[hHuetab[l]];
hBout[setSat];
hBout[hSattab[l]];
END;
hBout[setx];
hWout[a];
hBout[sety];
hWout[b];
hBout[showrect];
hWout[c - a];
hWout[d - b];
IF byteCnt > ovByteCnt + ovLimit THEN termEnt[];
END;
END;
termEnt: PROCEDURE =
BEGIN
IF byteCnt = ovByteCnt THEN RETURN;
IF BITAND[byteCnt, 1] # 0 THEN hBout[377];
hWout[0]; -- type,font set
hWout[0]; --..
hWout[0]; -- begin byte #
hWout[0]; -- first word of byte count
hWout[0]; -- second word of ditto
hWout[0]; -- Xe
hWout[0]; -- Ye
hWout[0]; -- left
hWout[0]; -- bottom
hWout[20600]; -- width
hWout[27460]; -- height
hWout[(byteCnt - ovByteCnt + 2)/2]; -- entity length
pagCnt ← pagCnt + byteCnt/512;
byteCnt ← byteCnt MOD 512;
ovByteCnt ← byteCnt;
currentColor ← NOcOL; -- make sure first color we output isn't current
END;
outWord: PROCEDURE [ww: UNSPECIFIED] = {hdcpyHandle.put[hdcpyHandle, ww]};
hBout: PROCEDURE [u: UNSPECIFIED] =
BEGIN
IF BITAND[byteCnt, 1] = 0 THEN saveByte ← BITSHIFT[BITAND[u, 377B], 8]
ELSE outWord[BITOR[saveByte, BITAND[u, 377B]]];
byteCnt ← byteCnt + 1;
END;
hWout: PROCEDURE [u: UNSPECIFIED] =
BEGIN
IF BITAND[byteCnt, 1] = 0 THEN BEGIN outWord[u]; byteCnt ← byteCnt + 2; END
ELSE BEGIN hBout[BITSHIFT[u, -8]]; hBout[u]; END;
END;
--************* error file reading stuff:
erfHan: DiskHandle;
gotErf: BOOLEAN ← FALSE;
erfLine: STRING ← [200];
gtByt: PROCEDURE RETURNS [CHARACTER] =
BEGIN
IF NOT erfHan.endof[erfHan] THEN RETURN[erfHan.get[erfHan]] ELSE RETURN[15C];
END;
rdErfLine: PUBLIC PROCEDURE RETURNS [x, y: INTEGER, s: STRING, nums: BOOLEAN] =
BEGIN
c: CHARACTER;
i, j: CARDINAL;
x ← y ← 0;
IF NOT gotErf OR erfHan.endof[erfHan] THEN
BEGIN s ← "NONE"; nums ← FALSE; RETURN; END;
erfLine.length ← 0;
s ← erfLine;
c ← 'a;
WHILE c # 15C AND s.length < s.maxlength DO
c ← gtByt[]; IF c # 15C THEN AppendChar[s, c]; ENDLOOP;
WHILE c # 15C DO c ← gtByt[]; ENDLOOP;
[x, i, nums] ← scanLine[s, 0];
IF nums THEN [y, i, nums] ← scanLine[s, i];
IF ~nums THEN i ← 0;
WHILE i < s.length AND s[i] = ' DO i ← i + 1; ENDLOOP;
IF i # 0 THEN
BEGIN
j ← 0;
WHILE i < s.length DO s[j] ← s[i]; i ← i + 1; j ← j + 1; ENDLOOP;
s.length ← j;
END;
END;
scanLine: PUBLIC PROCEDURE [s: STRING, i: CARDINAL]
RETURNS [v: INTEGER, j: CARDINAL, any: BOOLEAN] =
BEGIN
vv: LONG INTEGER;
minFlg: BOOLEAN ← FALSE;
vv ← 0;
j ← i;
any ← TRUE;
v ← 0;
WHILE j < s.length AND (s[j] = 40C OR s[j] = 11C) DO j ← j + 1; ENDLOOP;
IF j = s.length OR (s[j] # '- AND NOT s[j] IN ['0..'9]) THEN
BEGIN any ← FALSE; RETURN; END;
IF s[j] = '- THEN BEGIN minFlg ← TRUE; j ← j + 1; END;
WHILE j < s.length AND s[j] IN ['0..'9] DO
vv ← vv*10 + (s[j] - '0); j ← j + 1; ENDLOOP;
vv ← (vv*lambda)/pCifScale;
v ← LowHalf[IF minFlg THEN -vv ELSE vv];
END;
openErfile: PUBLIC PROCEDURE [fname: STRING] RETURNS [BOOLEAN] =
BEGIN
IF gotErf THEN erfHan.destroy[erfHan];
IF NOT DirectoryLookup[@fp, fname, FALSE] THEN RETURN[FALSE];
erfHan ← NewByteStream[fname, Read];
gotErf ← TRUE;
RETURN[TRUE];
END;
END.