<> <> <> <> <> DIRECTORY Atom USING [MakeAtom], Basics USING [BITAND, BITSHIFT], CD, CDInstances, CDBusCells USING [CreateBusCell], CDCells USING [CreateEmptyCell], CDMenus, CDSimpleOps, CDIO USING [MakeName], CDDirectory USING [Include], CDOps, CDOrient, CDProperties, CDRects USING [CreateRect], CDRepetitions, CDTexts, CDViewer, Commander USING [CommandProc, Register], CommandTool, FS, IO, CMos, CMosCMContacts, CMosCMTransistors, Rope, TerminalIO, ViewerClasses USING [Viewer]; ChipmonkCmosRead: CEDAR MONITOR IMPORTS Atom, Basics, CDInstances, CDBusCells, CDCells, CDSimpleOps, CDDirectory, CDIO, CDMenus, CDOps, CDProperties, CDRects, CDRepetitions, CDTexts, CDViewer, Commander, FS, IO, CMos, CMosCMContacts, CMosCMTransistors, CommandTool, Rope, TerminalIO SHARES CDProperties = BEGIN <<-- global constants>> lambdaInChipmonk: INTEGER = 2; <<--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>> lambdaFactor: INT = CMos.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 = 1500; 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 = [ CMos.ndif, CMos.pol, CMos.ndif, CMos.ndif, CMos.met2, CMos.pdif, CMos.nwellCont, CMos.ndif, CMos.pol, CMos.ndif, CMos.ndif, CMos.ndif ]; -- for versions < 6 fileLevel: ARRAY [0..15] OF CD.Layer = [ CMos.cut, CMos.ndif, CMos.pol, CMos.met, CMos.imp, CMos.ovg, CMos.bur, CD.errorLayer --snerd-- , CMos.cut2, CMos.pdif, CMos.pwellCont, CMos.met2, CMos.pwell, CMos.nwell, CMos.nwellCont, CD.errorLayer --NOcOL-- ]; <<-- global vars>> contType: TYPE = {burr, mDif, difShort, butt, mPol, mm2}; design: CD.Design; cellNameA: REF ARRAY [0..maxCellNum] OF CD.Object _ NEW[ARRAY [0..maxCellNum] OF CD.Object]; atomTable: REF ARRAY [1..atomTableSize] OF ATOM _ NEW[ARRAY [1..atomTableSize] OF ATOM]; standardFont: CDTexts.CDFont = CDTexts.MakeFont[name: "Xerox/TiogaFonts/Tioga10"]; chipfile: IO.STREAM; fileName: Rope.ROPE; errs: INT _0; NotYetImpl: PROC [] = BEGIN errs _ errs+1; TerminalIO.WriteRope["?"]; END; BadObject: PROC [size: CD.Position _ [4, 4]] RETURNS [CD.Object] = BEGIN RETURN [CDRects.CreateRect[size, CD.errorLayer]] 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.Number] = INLINE BEGIN RETURN [lambdaFactor*i] END; 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.Object, 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 aExt: CD.Number _ 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[LOOPHOLE[kk, CARDINAL], 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 [] _ InWord[]; -- implant }; we _ Basics.BITAND[Basics.BITSHIFT[kk, -6], 77B]; le _ Basics.BITAND[kk, 77B]; lev _ IF Basics.BITAND[kk, 10000B]#0 THEN CMos.pdif ELSE CMos.ndif; SELECT TRUE FROM LOOPHOLE[Basics.BITAND[kk, 40000B], CARDINAL] #0 => {obj _ NIL; TerminalIO.WriteRope[" error: pullup in cmos\n"]}; <> LOOPHOLE[Basics.BITAND[kk, 20000B], CARDINAL] #0 => obj _ CMosCMTransistors.CreateAngleTransistor[w: Lambda[w], l: Lambda[l], wExt: Lambda[we], lExt: Lambda[le], aExt: aExt, difLev: lev]; ENDCASE => obj _ CMosCMTransistors.CreateTransistor[w: Lambda[w], l: Lambda[l], wExt: Lambda[we], lExt: Lambda[le], difLev: lev]; END; contact => BEGIN j: CARDINAL _ LOOPHOLE[InWord[]]; -- get contact type k: CARDINAL _ Basics.BITAND[j, 37B]; -- get contact type l: CARDINAL _ Basics.BITSHIFT[j, -8]; lev _ IF version > 5 THEN InLevel[] ELSE contLevel[k]; IF version > 4 THEN dumsur _ LOOPHOLE[InWord[]]; SELECT contTypA[k] FROM mPol => obj _ CMosCMContacts.CreatePolyCon[Lambda[l]]; mDif => obj _ CMosCMContacts.CreateDifCon[Lambda[l], lev]; difShort => obj _ CMosCMContacts.CreateDifShortCon[lev]; butt => obj_ CMosCMContacts.CreateButCon[lev]; burr => BEGIN w _ LOOPHOLE[InWord[]]; k _ LOOPHOLE[InWord[]]; j _ Basics.BITSHIFT[k, -8]; obj _ CMosCMContacts.CreateBurCon[w: Lambda[w], l: Lambda[l], wex: Lambda[j], lex: Lambda[LOOPHOLE[Basics.BITAND[k, 37B], CARDINAL]], difLev: lev]; END; mm2 => obj _ CMosCMContacts.CreateMmCon[Lambda[l], 0, 0]; ENDCASE => {TerminalIO.WriteRope[" Error in selecting contact type "]; ERROR}; END; wire => BEGIN i: INTEGER; w _ InWord[]; l _ InWord[]; i _ InWord[]; lev _ ToLevel[i]; IF lev=CMos.pdif THEN lev _ CMos.wpdif; SELECT i FROM 7 => {appVal _ $snerdRect; appProp _ $SignalName}; 15 => {appVal _ $NOcOLRect; appProp _ $SignalName}; ENDCASE => NULL; IF version > 4 AND lev = CMos.wpdif THEN dumsur _ InWord[]; 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]; IF lev=CMos.pdif THEN lev _ CMos.wpdif; 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.Number = Lambda[InWord[]]; l: CD.Number = Lambda[InWord[]]; lev: CD.Layer = InLevel[]; count: NAT = InWord[]; spacing: CD.Number = Lambda[InWord[]]; topInc: CD.Number = Lambda[InWord[]]; botInc: CD.Number = Lambda[InWord[]]; IF lev=CMos.pdif THEN {TerminalIO.WriteRope["**bus implant is not drawn\n"]}; 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.Object = InObject[version].obj; ignoredw: INT = InWord[]; -- ignored ignoredl: INT = InWord[]; -- ignored dx: CD.Number = Lambda[InWord[]]; dy: CD.Number = 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"]; }; END; -- InObject InList: PROC[ver: INTEGER] RETURNS [list: CD.InstanceList _ NIL, length: INT] = BEGIN appProp: REF _ NIL; appVal: REF _ NIL; appCount: INTEGER; inst: CD.Instance; ob: CD.Object; location: CD.Position; 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"] }; inst _ CDInstances.NewInstI[ob: ob, location: location, orientation: orientation]; list _ CONS[inst, list]; IF appProp#NIL THEN CDProperties.PutInstanceProp[onto: inst, prop: appProp, val: appVal]; IF ver > 3 THEN BEGIN propCount: INTEGER = InWord[]; FOR propNum: INTEGER IN [0..propCount) DO InProp[inst]; ENDLOOP; END; ENDLOOP; IF debugging OR debug THEN TerminalIO.WriteRope["end list\n"]; RETURN[list, appCount]; END; sigName: ATOM = Atom.MakeAtom["SIGNAL NAME"]; InProp: PROC [inst: CD.Instance] = BEGIN kind: INTEGER _ InWord[]; name: REF _ NIL; value: REF; SELECT kind FROM 1 => { IF inst=NIL OR inst.ob=NIL OR ISTYPE[inst.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 inst#NIL AND inst.ob#NIL THEN CDProperties.PutProp[onto: inst, 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, len: CARDINAL; flg: BOOLEAN; j _ LOOPHOLE[InWord[]]; len _ Basics.BITSHIFT[j, -8]; IF len = 0 THEN BEGIN s _ ""; RETURN; END; flg _ TRUE; FOR i: CARDINAL IN [0..len) DO IF flg THEN s _ Rope.Cat[s, Rope.FromChar[LOOPHOLE[Basics.BITAND[j, 377B], CHAR]]] ELSE { j _ LOOPHOLE[InWord[]]; s _ Rope.Cat[s, Rope.FromChar[LOOPHOLE[Basics.BITSHIFT[j, -8], CHAR]]]; }; 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.WriteRopes[fileName, " not opened: ", error.explanation]; TerminalIO.WriteLn[]; GOTO FileName }]; TerminalIO.WriteRopes["File being read is ", fileName, "\n"]; fileWasOpened _ TRUE; EXITS FileName => {fileWasOpened _ FALSE}; END; ResetSimplification: PROC[cell: CD.Object, 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]; is: INT; leng _ leng/2+6; leng _ MAX[MIN[leng, 300], 8]; <<--make it symetric now using shorter size>> IF cell.size.y>cell.size.x THEN { leng _ (leng*long)/short; }; leng _ MAX[MIN[leng, 600], 8]; <<--introduce longer side>> leng _ (leng*3)/(2+(long/short)/2); is _ MAX[MIN[leng, 600], 8]; cp.simplifyOn _ is; END; signal: SIGNAL = CODE; ReadChip: PROC = BEGIN ENABLE { FileFormat => { TerminalIO.WriteRope["\n**File-Format error [proceed does not clobber other designs]\n"]; SIGNAL signal; GOTO IOError; }; IO.EndOfStream => { TerminalIO.WriteRope["\n**end of stream error [proceed does not clobber other designs]\n"]; SIGNAL signal; GOTO IOError; }; IO.Error => { TerminalIO.WriteRope["\n**io error[proceed does not clobber other designs]\n"]; <<--if you are debugging here: inspect "ec">> SIGNAL signal; GOTO IOError; }; }; i, j, k, ver, cCnt, depht: INTEGER; leng: INT; ss: Rope.ROPE; cdp: CD.Object; cellPtr: CD.CellPtr; errs _ 0; i _ InWord[]; IF i # LOOPHOLE[codeWordForDataFile, INTEGER] AND NOT TerminalIO.Confirm[label: "Doesn't look like a .chip file", choice: "continue"] THEN RETURN; ver _ InWord[]; cCnt _ InWord[]; IF cCnt > maxCellNum THEN { TerminalIO.WriteRope["Too many different kinds of cells in design...aborting read\n"]; RETURN; }; IF ver < 3 THEN { TerminalIO.WriteRope[" Version number too low...aborting read\n"]; RETURN; }; IF ver>8 THEN { TerminalIO.WriteRope[" new chipmonk version unknown to chipndale...aborting read\n"]; RETURN; }; 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[]]; [] _ InWord[]; -- this is some count in chipmonk ?? 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 { --empty cell TerminalIO.WriteRope[Rope.Cat["** empty cell ", cellPtr.name, "\n"]]; cellPtr.contents _ LIST[CDInstances.NewInstI[BadObject[]]]; }; ResetSimplification[cdp, leng]; cellPtr.ir _ CDInstances.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.WriteF1["%g unknown objects\n", IO.int[errs]]; errs _ 0; }; IO.Close[chipfile]; EXITS IOError => {TerminalIO.WriteRope[" proceed; discard this design\n"];}; END; -- 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[CMos.cmos]; 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; TestRead: ENTRY Commander.CommandProc = BEGIN ENABLE { IO.EndOfStream => GOTO IOEnd; UNWIND => NULL; }; w: CARDINAL; IF FileOpened[NIL] THEN { TerminalIO.WriteRope["--startfile--\n"]; DO w _ LOOPHOLE[InWord[]]; TerminalIO.WriteF1["%7b\n", IO.card[w]]; ENDLOOP; }; EXITS IOEnd => {TerminalIO.WriteRope["--endfile--\n"]}; END; CDMenus.CreateEntry[$IOMenu, "chipmonk-output", $ChipmonkOutput]; Commander.Register[ key: "CDTestRead", proc: TestRead, doc: "Reads file and display it on Terminal" ]; Commander.Register[ key: "CDReadCMos", proc: CommandReadChip, doc: "Reads old cmos Chipmonk file" ]; Commander.Register[ key: "CDReadCMCMos", proc: CommandReadChip, doc: "Reads old cmos Chipmonk file" ]; END.