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