DIRECTORY Atom USING [MakeAtom], Basics USING [BITAND, BITSHIFT], CD, CDApplications, CDBusCells USING [CreateBusCell], CDCells USING [CreateEmptyCell], CDSimpleOps, CDDirectory USING [Include], CDIO, CDMenus, CDOps, CDOrient, CDPrivate, CDProperties, CDRects USING [CreateRect], CDRepetitions, CDTexts, CDViewer, Commander USING [CommandProc, Register], CommandTool, FS, IO, NMos, NMosContacts, NMosTransistors, Rope USING [ROPE, Cat, IsEmpty, FromChar], TerminalIO, ViewerClasses USING [Viewer]; ChipmonkNMosRead: CEDAR MONITOR IMPORTS Atom, Basics, CDApplications, CDBusCells, CDCells, CDSimpleOps, CDDirectory, CDIO, CDMenus, CDOps, CDPrivate, CDProperties, CDRects, CDRepetitions, CDTexts, CDViewer, Commander, CommandTool, FS, IO, NMos, NMosContacts, NMosTransistors, Rope, TerminalIO SHARES CDProperties = BEGIN lambdaInChipmonk: INTEGER = 2; lambdaFactor: INT = CD.lambda/lambdaInChipmonk; instance: INTEGER = 1; transistor: INTEGER = 2; contact: INTEGER = 3; wire: INTEGER = 4; rectangle: INTEGER = 5; text: INTEGER = 6; bus: INTEGER = 7; repeat: INTEGER = 8; contTypALen: INTEGER = 12; maxCellNum: INTEGER = 500; codeWordForDataFile : CARDINAL = 123751B; debugging: BOOLEAN = FALSE; debug: BOOLEAN = FALSE; atomTableSize: INTEGER = 256; contTypA: ARRAY [1..contTypALen] OF contType = [ mDif, mPol, butt, burr, mm2, mDif, mDif, mm2, mm2, mm2, mm2, difShort ]; contLevel: ARRAY [1..contTypALen] OF CD.Layer = [ NMos.dif, NMos.pol, NMos.dif, NMos.dif, NMos.met2, NMos.dif, NMos.nwelCont, NMos.dif, NMos.pol, NMos.dif, NMos.dif, NMos.dif ]; -- for versions < 6 fileLevel: ARRAY [0..15] OF CD.Layer = [ NMos.cut, NMos.dif, NMos.pol, NMos.met, NMos.imp, NMos.ovg, NMos.bur, CD.highLightError --snerd-- , NMos.cut2, CD.highLightError--pdif--, CD.highLightError--pwelcont--, NMos.met2, CD.highLightError--pwel--, NMos.nwel, NMos.nwelCont, CD.highLightError --NOcOL-- ]; contType: TYPE = {burr, mDif, difShort, butt, mPol, mm2}; design: CD.Design; cellNameA: REF ARRAY [0..maxCellNum] OF CD.ObPtr _ NEW[ARRAY [0..maxCellNum] OF CD.ObPtr]; atomTable: REF ARRAY [1..atomTableSize] OF ATOM _ NEW[ARRAY [1..atomTableSize] OF ATOM]; standardFont: REF CDTexts.FontRec = CDTexts.GetFont[key: $CDxCompatibilityFont, technology: NMos.nmos]; chipfile: IO.STREAM; fileName: Rope.ROPE; errs: INT _0; NotYetImpl: PROC [] = BEGIN errs _ errs+1; TerminalIO.WriteRope["?"]; END; BadObject: PROC [size: CD.DesignPosition _ [4, 4]] RETURNS [CD.ObPtr] = BEGIN RETURN [CDRects.CreateRect[size, CD.highLightError]] END; InWord: PROC RETURNS [INTEGER] = BEGIN highbyte: CARDINAL = LOOPHOLE[IO.GetChar[chipfile], CARDINAL]; lowbyte: CARDINAL = LOOPHOLE[IO.GetChar[chipfile], CARDINAL]; RETURN [ LOOPHOLE[(256*highbyte) + lowbyte, INTEGER] ]; END; FileFormat: ERROR = CODE; Lambda: PROCEDURE [i: INT] RETURNS [CD.DesignNumber] = INLINE { RETURN [lambdaFactor*i] }; InOrientation: PROC [] RETURNS [CD.Orientation] = INLINE BEGIN i: INTEGER = InWord[]; IF i>=0 AND i<=15 THEN RETURN [i/4*2 + i MOD 2] --different representation ELSE ERROR FileFormat; END; ToLevel: PROC [i: INTEGER] RETURNS [CD.Layer] = INLINE BEGIN IF i>= 0 AND i<= 15 THEN RETURN [fileLevel[i]] ELSE ERROR FileFormat; END; InLevel: PROC [] RETURNS [CD.Layer] = INLINE BEGIN RETURN [ToLevel[InWord[]]] END; NewCellName: PROC [index: INTEGER] RETURNS [cellName: Rope.ROPE] = BEGIN cellName _ IO.PutFR[ "cell#%d", IO.int[index]]; END; InObject: PROC[version: INTEGER] RETURNS [obj: CD.ObPtr, appProp: REF_NIL, appVal: REF_NIL] = BEGIN j, k, w, l, we, le, dumsur : INTEGER; kk: CARDINAL; lev: CD.Layer; dumrope: Rope.ROPE; IF debugging OR debug THEN TerminalIO.WriteRope[" (Include new object ... "]; j _ InWord[]; SELECT j FROM instance => BEGIN k _ InWord[]; -- cell ID num obj _ cellNameA[k]; END; transistor => BEGIN impl: NMosTransistors.Implant _ NMosTransistors.enhancement; aExt: CD.DesignNumber _ 0; w _ InWord[]; l _ InWord[]; kk _ LOOPHOLE[InWord[]]; IF version > 4 AND LOOPHOLE[Basics.BITAND[kk, 10000B], CARDINAL] # 0 THEN dumsur _ InWord[]; IF LOOPHOLE[Basics.BITAND[kk, 20000B], CARDINAL] # 0 THEN aExt _ Lambda[InWord[]]; -- if angle get angle ext. IF LOOPHOLE[Basics.BITAND[kk, 100000B], CARDINAL]#0 THEN { IF version>7 THEN impl _ InWord[] ELSE impl _ LAST[NMosTransistors.Implant] }; we _ Basics.BITAND[Basics.BITSHIFT[kk, -6], 77B]; le _ Basics.BITAND[kk, 77B]; obj _ SELECT TRUE FROM LOOPHOLE[Basics.BITAND[kk,40000B], CARDINAL] #0 => NMosTransistors.CreatePullUp[Lambda[w], Lambda[l], Lambda[we], Lambda[le]], LOOPHOLE[Basics.BITAND[kk, 20000B], CARDINAL] #0 => NMosTransistors.CreateAngleTransistor[ w: Lambda[w], l: Lambda[l], wExt: Lambda[we], lExt: Lambda[le], aExt: aExt, implant: impl ], ENDCASE => NMosTransistors.CreateTransistor[ w: Lambda[w], l: Lambda[l], wExt: Lambda[we], lExt: Lambda[le], implant: impl ]; END; contact => BEGIN j: CARDINAL _ LOOPHOLE[InWord[]]; -- get contact type kk: CARDINAL _ Basics.BITAND[j, 37B]; -- get contact type l: CARDINAL _ Basics.BITSHIFT[j, -8]; lev _ IF version > 5 THEN InLevel[] ELSE contLevel[kk]; IF version > 4 THEN dumsur _ LOOPHOLE[InWord[]]; SELECT contTypA[kk] FROM mPol => obj _ NMosContacts.CreatePolyCon[Lambda[l]]; mDif => obj _ NMosContacts.CreateDifCon[Lambda[l]]; butt => obj_ NMosContacts.CreateButCon[]; burr => BEGIN w _ LOOPHOLE[InWord[]]; kk _ LOOPHOLE[InWord[]]; j _ Basics.BITSHIFT[kk, -8]; obj _ NMosContacts.CreateBurCon[Lambda[w], Lambda[l], Lambda[j], Lambda[LOOPHOLE[Basics.BITAND[kk, 37B], CARDINAL]]]; END; mm2 => obj _ NMosContacts.CreateMmCon[Lambda[l], 0, 0]; ENDCASE => ERROR; END; wire => BEGIN i: INTEGER; w _ InWord[]; l _ InWord[]; i _ InWord[]; lev _ ToLevel[i]; SELECT i FROM 7 => {appVal _ $snerdRect; appProp _ $SignalName}; 15 => {appVal _ $NOcOLRect; appProp _ $SignalName}; ENDCASE => NULL; obj _ CDRects.CreateRect[[Lambda[w],Lambda[l]], lev]; END; rectangle => BEGIN i: INTEGER; w _ InWord[]; l _ InWord[]; appVal _ $Rect; appProp _ $CDxChipmonkThinks; i _ InWord[]; lev _ ToLevel[i]; SELECT i FROM 7 => {appVal _ $snerdRect; appProp _ $SignalName}; 15 => {appVal _ $NOcOLRect; appProp _ $SignalName}; ENDCASE => NULL; obj _ CDRects.CreateRect[[Lambda[w], Lambda[l]], lev]; END; text => { dumrope _ InString[]; obj _ CDTexts.CreateText[dumrope, standardFont] }; bus => BEGIN w: CD.DesignNumber = Lambda[InWord[]]; l: CD.DesignNumber = Lambda[InWord[]]; lev: CD.Layer = InLevel[]; count: NAT = InWord[]; spacing: CD.DesignNumber = Lambda[InWord[]]; topInc: CD.DesignNumber = Lambda[InWord[]]; botInc: CD.DesignNumber = Lambda[InWord[]]; obj _ CDBusCells.CreateBusCell[ design: design, sizeOfFirst: [w, l], lev: lev, count: count, offset: [spacing, topInc], lengIncrement: botInc-topInc ]; -- compare: obj _ Chipmonk.makeBus[l, w, lev, count, spacing, topInc, botInc]; END; repeat => BEGIN rob: CD.ObPtr = InObject[version].obj; ignoredw: INT = InWord[]; -- ignored ignoredl: INT = InWord[]; -- ignored dx: CD.DesignNumber = Lambda[InWord[]]; dy: CD.DesignNumber = Lambda[InWord[]]; count: NAT _ InWord[]; orient: CD.Orientation _ InOrientation[]; obj _ CDRepetitions.CreateRepetition[design: design, ob: rob, count: count, offset: [dx, dy], orientation: orient]; END; ENDCASE => { obj _ BadObject[]; TerminalIO.WriteRope["** Erronous object\n"]; }; IF debugging OR debug THEN TerminalIO.WriteRope[" done) \n"]; END; -- of InObject InList: PROC[ver: INTEGER] RETURNS [list: CD.ApplicationList _ NIL, length: INT] = BEGIN appProp: REF _ NIL; appVal: REF _ NIL; appCount: INTEGER; app: CD.ApplicationPtr; ob: CD.ObPtr; location: CD.DesignPosition; orientation: CD.Orientation; IF debugging OR debug THEN TerminalIO.WriteRope["start list\n"]; appCount _ InWord[]; FOR appNum: INTEGER IN [0..appCount) DO location.x _ Lambda[InWord[]]; location.y _ Lambda[InWord[]]; orientation _ InOrientation[]; [ob, appProp, appVal] _ InObject[ver]; IF ob=NIL THEN { ob _ BadObject[]; TerminalIO.WriteRope["nil object\n"] }; app _ CDApplications.NewApplicationI[ob: ob, location: location, orientation: orientation]; list _ CONS[app, list]; IF appProp#NIL THEN CDProperties.PutPropOnApplication[onto: app, prop: appProp, val: appVal]; IF ver > 3 THEN BEGIN propCount: INTEGER = InWord[]; FOR propNum: INTEGER IN [0..propCount) DO InProp[app]; ENDLOOP; END; ENDLOOP; RETURN[list, appCount]; END; sigName: ATOM = Atom.MakeAtom["SIGNAL NAME"]; InProp: PROC [aptr: CD.ApplicationPtr] = BEGIN kind: INTEGER _ InWord[]; name: REF _ NIL; value: REF; SELECT kind FROM 1 => { IF aptr=NIL OR aptr.ob=NIL OR ISTYPE[aptr.ob.specificRef, CD.RectPtr] THEN name _ $SignalName ELSE name _ $InstanceName; value _ InString[]; }; 2 => { name _ InAtom[]; value _ InAtom[]; IF name=sigName THEN name _ $SignalName; }; ENDCASE => { name _ NIL; TerminalIO.WriteRope["** unknown property kind\n"]; }; IF name#NIL AND aptr#NIL AND aptr.ob#NIL THEN CDProperties.PutProp[onto: aptr, prop: name, val: value] END; InAtom: PROC [] RETURNS[a: ATOM] = BEGIN i: INTEGER _ InWord[]; IF i<0 THEN { a _ atomTable[-i] } ELSE IF i>0 THEN { a _ Atom.MakeAtom[InString[]]; IF i <= atomTableSize THEN atomTable[i] _ a ELSE TerminalIO.WriteRope["** Atom table code wrong\n"]; } ELSE { TerminalIO.WriteRope["** Atom code wrong\n"]; a _ NIL } END; InString: PROC [] RETURNS[s: Rope.ROPE] = BEGIN j, i, len: CARDINAL; flg: BOOLEAN; j _ LOOPHOLE[InWord[]]; len _ Basics.BITSHIFT[j, -8]; IF len = 0 THEN BEGIN s _ ""; RETURN; END; flg _ TRUE; FOR i IN [0..len) DO IF flg THEN s _ Rope.Cat[s, Rope.FromChar[LOOPHOLE[Basics.BITAND[j, 377B], CHAR]]] ELSE BEGIN j _ LOOPHOLE[InWord[]]; s _ Rope.Cat[s, Rope.FromChar[LOOPHOLE[Basics.BITSHIFT[j, -8], CHAR]]]; END; flg _ NOT flg; ENDLOOP; END; FileOpened: PROC [name: Rope.ROPE] RETURNS [fileWasOpened: BOOLEAN] = BEGIN IF Rope.IsEmpty[name] THEN name _ TerminalIO.RequestRope["Input file > "]; fileName _ CDIO.MakeName[name, "chip"]; chipfile _ FS.StreamOpen[fileName ! FS.Error => IF error.group#bug THEN { TerminalIO.WriteRope[fileName]; TerminalIO.WriteRope[" not opened: "]; TerminalIO.WriteRope[error.explanation]; TerminalIO.WriteLn[]; GOTO FileName }]; TerminalIO.WriteRope["File being read is "]; TerminalIO.WriteRope[fileName]; TerminalIO.WriteRope["\n"]; fileWasOpened _ TRUE; EXITS FileName => {fileWasOpened _ FALSE}; END; ResetSimplification: PROC[cell: CD.ObPtr, leng: INT_0] = INLINE BEGIN long: INT ~ MAX[MAX[cell.size.y, cell.size.x], 1]; short: INT ~ MAX[MIN[cell.size.y, cell.size.x], 1]; cp: CD.CellPtr ~ NARROW[cell.specificRef]; leng _ leng/2+6; leng _ MAX[MIN[leng, 300], 8]; IF cell.size.y>cell.size.x THEN { leng _ (leng*long)/short; }; leng _ MAX[MIN[leng, 600], 8]; leng _ (leng*3)/(2+(long/short)/2); cp.simplifyOn _ MAX[MIN[leng, 600], 8]; END; ReadChip: PROC = BEGIN ENABLE { FileFormat => { TerminalIO.WriteRope["\n**File-Format error\n"]; CDPrivate.Debug[msg: "file format; [proceed does not clobber other designs]"]; GOTO IOError; }; IO.EndOfStream => { TerminalIO.WriteRope["\n**end of stream error\n"]; CDPrivate.Debug[msg: "file format; [proceed does not clobber other designs]"]; GOTO IOError; }; IO.Error => { TerminalIO.WriteRope["\n**io error\n"]; CDPrivate.Debug[msg: "io error [proceed does not clobber other designs]"]; GOTO IOError; }; }; i, j, k, ver, cCnt, dummy, depht: INTEGER; leng: INT; ss: Rope.ROPE; cdp: CD.ObPtr; cellPtr: CD.CellPtr; errs_0; i _ InWord[]; IF i # LOOPHOLE[codeWordForDataFile, INTEGER] AND NOT TerminalIO.UserSaysYes[ "Doesn't look like a .chip file -- should program continue?"] THEN RETURN; ver _ InWord[]; cCnt _ InWord[]; IF cCnt > maxCellNum THEN BEGIN TerminalIO.WriteRope["Too many different kinds of cells in design...aborting read\n"]; RETURN; END; IF ver < 3 THEN BEGIN TerminalIO.WriteRope[" Version number too low...aborting read\n"]; RETURN; END; IF ver>8 THEN BEGIN TerminalIO.WriteRope[" new chipmonk version unknown to chipndale...aborting read\n"]; RETURN; END; FOR j IN [0..cCnt] DO cellNameA[j] _ CDCells.CreateEmptyCell[]; ENDLOOP; TerminalIO.WriteRope["Starting cell directory\n"]; FOR k IN [1..cCnt] DO j _ InWord[]; cdp _ cellNameA[j]; ss _ InString[]; cdp.size.x _ Lambda[InWord[]]; cdp.size.y _ Lambda[InWord[]]; dummy _ InWord[]; cellPtr _ NARROW[cdp.specificRef, CD.CellPtr]; [cellPtr.contents, leng] _ InList[ver]; IF NOT Rope.IsEmpty[ss] THEN cellPtr.name _ ss ELSE cellPtr.name _ NewCellName[k]; [] _ CDDirectory.Include[design: design, object: cdp, fiddleName: TRUE]; IF cellPtr.contents=NIL THEN { TerminalIO.WriteRope[Rope.Cat["** empty cell ", cellPtr.name, "\n"]]; cellPtr.contents _ LIST[CDApplications.NewApplicationI[BadObject[]]]; }; ResetSimplification[cdp, leng]; cellPtr.ir _ CDApplications.BoundingRectI[cellPtr.contents]; ENDLOOP; TerminalIO.WriteRope["Finished cell directory\n"]; depht _ IF ver<7 THEN 0 ELSE InWord[]; IF depht>0 THEN { TerminalIO.WriteRope["***design was pushed in; not read in correctly\n"]; RETURN; }; IF ver>=7 THEN { fileChangeCode: INTEGER = InWord[]; }; design.actual.first.specific.contents _ InList[ver].list; design.name _ fileName; TerminalIO.WriteRope["Finished reading chip\n"]; IF errs>0 THEN { TerminalIO.WriteInt[errs]; TerminalIO.WriteRope[" unknown objects\n"]; errs _ 0; }; IO.Close[chipfile]; EXITS IOError => {TerminalIO.WriteRope[" proceed; discard this design\n"];}; END; -- of ReadChip CommandReadChip: ENTRY Commander.CommandProc = BEGIN ENABLE { TerminalIO.UserAbort => GOTO UserAbrt; UNWIND => NULL; }; list: LIST OF Rope.ROPE; length: NAT; name: Rope.ROPE; [list, length] _ CommandTool.ParseToList[cmd]; IF length=0 THEN name_NIL ELSE IF length=1 THEN name_list.first ELSE { result_$Failure; msg_"unknown arguments"; RETURN }; design_ CDOps.CreateDesign[NMos.nmos]; IF FileOpened[name] THEN { ReadChip[]; CDSimpleOps.SelectAll[design]; CDSimpleOps.TransformSelected[design, CDOrient.rotate180+CDOrient.mirrorX]; CDSimpleOps.DeselectAll[design]; [] _ CDViewer.CreateViewer[design]; }; EXITS UserAbrt => {TerminalIO.WriteRope["read aborted\n"]}; END; CDMenus.CreateEntry[$IOMenu, "chipmonk-output", $ChipmonkOutput]; Commander.Register[ key: "CDReadNMos", proc: CommandReadChip, doc: "Reads old nmos Chipmonk file" ]; Commander.Register[ key: "CDReadCMNMos", proc: CommandReadChip, doc: "Reads old nmos Chipmonk file" ]; END. ψChipmonkNMosRead.mesa Copyright c 1983, 1985 by Xerox Corporation. All rights reserved. Last Edited by: Kimr, October 26, 1983 9:39 am Last Edited by: Jacobi, October 25, 1983 12:48 pm Last Edited by: Jacobi, April 11, 1985 11:15:40 am PST copy from cmos to nmos, not inverse! -- global constants --In Chipndale we must make no assumptions about the --value of lambda. It can (and does) change from time to time; --but we know that chipndales lambda is >= 2 -- global vars --lev _ IF Basics.BITAND[kk, 10000B] # LOOPHOLE[0] THEN NMos.pdif ELSE NMos.dif; -- difShort => obj _ NMosContacts.CreateDifShortCon[lev]; ************ --get file name --make it symetric now using shorter size --introduce longer side --if you are debugging here: inspect "ec" Κή˜code•StartOfExpansionl[r1: ROPE _ NIL, r2: ROPE _ NIL, r3: ROPE _ NIL, r4: ROPE _ NIL, r5: ROPE _ NIL, r6: ROPE _ NIL]šœ™Kšœ Οmœ7™BKšœ.™.Kšœ1™1Kšœ6™6K™$—K˜K˜šΟk ˜ Kšœžœ ˜Kšœžœžœžœ˜ Kšžœ˜Kšœ˜Kšœ žœ˜!Kšœžœ˜ Kšœ ˜ Jšœ žœ ˜Kšœ˜Kšœ ˜ Kšœ˜K˜ Kšœ ˜ Kšœ ˜ Kšœžœ˜K˜K˜K˜ Kšœ žœ˜(K˜ Kšœ˜Kšžœ˜Kšœ˜Kšœ ˜ Kšœ˜Kšœžœžœ˜*Kšœ ˜ Kšœžœ ˜—K˜šΟbœžœž˜KšžœΔžœ8˜…Kšžœ˜—Kšž˜K˜šœ™K˜šœžœ˜ KšΟc5™5Kš ?™?Kš ,™,—Kšœžœžœ˜/K˜Kšœ žœ˜Kšœ žœ˜Kšœ žœ˜Kšœžœ˜Kšœ žœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜K˜Kšœ žœ˜Kšœ žœ˜Kšœžœ ˜)Kšœ žœžœ˜Kšœžœžœ˜Kšœžœ˜šœ žœžœ ˜1Kšœ˜Kšœ˜Kšœ˜Kšœ˜—šœ žœžœžœ ˜1Kšœ(˜(Kšœ.˜.Kšœ&˜&Kšœ ˜—šœ žœ žœžœ ˜(Kšœ(˜(Kšœžœ  œ˜Kš œ žœžœžœžœ˜=Kšžœžœžœ˜7Kšžœ˜K˜—Kšœ žœžœ˜K˜š ‘œž œžœžœžœ˜7Kšžœžœ˜#K˜—š‘ œžœžœžœ˜1Kšžœž˜ Kšœžœ ˜Kš žœžœžœžœ žœ ˜JKšžœžœ ˜Kšžœ˜K˜—š ‘œžœžœžœžœ ˜/Kšžœž˜ Kšžœžœžœžœ˜.Kšžœžœ ˜Kšžœ˜—K˜š‘œžœžœžœ ˜%Kšžœž˜ Kšžœ˜Kšžœ˜—K˜š ‘ œžœ žœžœžœ˜BKšž˜Kšœ žœžœ ˜/Kšžœ˜—K˜š‘œžœ žœžœžœžœžœ žœžœ˜^Kšž˜Kšœžœ˜%Kšœžœ˜ Kšœžœ˜Kšœžœ˜K˜šžœ žœž˜Kšœ2˜2—Kšœ˜šžœž˜ šœ ˜ Kšž˜Kšœ ˜Kšœ˜Kšžœ˜K˜—šœ ˜ Kšž˜Kšœ<˜