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