DIRECTORY Ascii, Atom, Basics USING [BITOR, BITSHIFT], CD, CDInstances, CDBasics, CDCells, CDCellsBackdoor, CDCommandOps, CDDirectory, CDIO, CDOps, CDProperties, CDRects, CDRepetitions, CDSequencer, CDTexts, CDViewer, FileNames, FS, HashTable, IO, NMos, NMosContacts, NMosTransistors, Rope, RuntimeError, TerminalIO; ChipmonkNMosWrite: CEDAR MONITOR IMPORTS Ascii, Atom, Basics, CD, CDBasics, CDCells, CDCellsBackdoor, CDCommandOps, CDDirectory, CDInstances, CDIO, CDOps, CDProperties, CDSequencer, FileNames, FS, HashTable, IO, NMos, Rope, RuntimeError, TerminalIO = BEGIN TransformSelected: PROC [design: CD.Design, transform: CD.Orientation, base: CD.Rect_[0, 0, -1, -1]] = { ib, is, orientOff: CD.Position; r, oldbb: CD.Rect; oldPseudoCellT, newPseudoCellT: CD.Transformation; sel: CD.InstanceList = CDInstances.OnlySelected[CDOps.InstList[design]]; IF sel=NIL THEN RETURN; oldbb _ CDInstances.BoundingRectO[sel]; IF ~CDBasics.NonEmpty[base] THEN base _ CDInstances.BoundingRectI[sel]; ib _ CDBasics.BaseOfRect[base]; is _ CDBasics.SizeOfRect[base]; oldPseudoCellT _ [ib, original]; r _ CDBasics.MapRect[CDBasics.RectAt[[0,0], is], [[0,0], transform]]; orientOff _ CDBasics.BaseOfRect[r]; newPseudoCellT _ [CDBasics.SubPoints[ib, orientOff], transform]; FOR w: CD.InstanceList _ sel, w.rest WHILE w#NIL DO pseudoCellRel: CD.Transformation _ CDBasics.DecomposeTransform[w.first.trans, oldPseudoCellT]; w.first.trans _ CDBasics.ComposeTransform[pseudoCellRel, newPseudoCellT] ENDLOOP; CDOps.Redraw[design, oldbb]; CDOps.Redraw[design, CDBasics.MapRect[CDBasics.DeMapRect[oldbb, oldPseudoCellT], newPseudoCellT]] }; lambdaInChipmonk: INTEGER = 2; lambdaFactor: INT = NMos.lambda/lambdaInChipmonk; codeWordForDataFile: CARDINAL = 123751B; instanceCode: INTEGER = 1; transistorCode: INTEGER = 2; contactCode: INTEGER = 3; wireCode: INTEGER = 4; rectangleCode: INTEGER = 5; textCode: INTEGER = 6; busCode: INTEGER = 7; repeatCode: INTEGER = 8; stream: IO.STREAM; PushedState: ERROR = CODE; gMark: HashTable.Table _ NIL; OutWord: PROC [w: INT] = BEGIN i: INTEGER = w; --traps if necessary c: CARDINAL _ LOOPHOLE[i, CARDINAL]; IO.PutChar[stream, LOOPHOLE[c / 256, CHAR]]; IO.PutChar[stream, LOOPHOLE[c MOD 256, CHAR]]; END; OutNumber: PROC [n: CD.Number] = -- does a lambda correction BEGIN i: INTEGER = n / lambdaFactor ; --traps if necessary c: CARDINAL = LOOPHOLE[i]; IO.PutChar[stream, LOOPHOLE[c / 256, CHAR]]; IO.PutChar[stream, LOOPHOLE[c MOD 256, CHAR]]; END; OutCard: PROC [c: CARDINAL] = BEGIN IO.PutChar[stream, LOOPHOLE[c / 256]]; IO.PutChar[stream, LOOPHOLE[c MOD 256]]; END; OutRope: PROC [r: Rope.ROPE] = BEGIN leng: [0..256) = MIN[Rope.Length[r], 255]; IO.PutChar[stream, LOOPHOLE[leng, CHAR]]; FOR i: CARDINAL IN [0..leng) DO IO.PutChar[stream, Rope.Fetch[base: r, index: i]]; ENDLOOP; IF leng MOD 2 = 0 THEN IO.PutChar[stream, LOOPHOLE[0, CHAR]]; END; OutRopeUpper: PROC [r: Rope.ROPE] = BEGIN leng: [0..256) = MIN[Rope.Length[r], 255]; IO.PutChar[stream, LOOPHOLE[leng, CHAR]]; FOR i: CARDINAL IN [0..leng) DO IO.PutChar[stream, Ascii.Upper[Rope.Fetch[base: r, index: i]]]; ENDLOOP; IF leng MOD 2 = 0 THEN IO.PutChar[stream, LOOPHOLE[0, CHAR]]; END; OutLevel: PROC [lev: CD.Layer] = BEGIN OutCard[levelTab[lev]] END; OutSize: PROC [s: CD.Position] = BEGIN OutNumber[s.x]; OutNumber[s.y]; END; OutRect: PROC [r: CD.Rect] = BEGIN OutNumber[r.x1]; OutNumber[r.y1]; OutNumber[r.x2]; OutNumber[r.y2]; END; cellCount: NAT; outputedCellCount: NAT; maxnum: NAT = 2000; cellNameA: REF ARRAY [0..maxnum) OF CD.Object; design: CD.Design; unKnowns: INT _ 0; unknownObjects: INT _ 0; unknownAtoms: INT _ 0; levelTab: REF ARRAY CD.Layer OF [0..15] = NEW[ARRAY CD.Layer OF [0..15]_ALL[15]]; contactTab: REF ARRAY NMosContacts.ContactType OF CARDINAL _ NEW[ARRAY NMosContacts.ContactType OF CARDINAL]; EachEntryCount: CDDirectory.EachEntryAction = BEGIN WITH ob.specific SELECT FROM cptr: CD.CellSpecific => {cellCount _ cellCount+1}; ENDCASE => NULL; END; EachChild: CDDirectory.EachObjectProc = { IF me.class.composed THEN [] _ EachEntryOutput[name: NIL, ob: me]; }; EachEntryOutput: CDDirectory.EachEntryAction = BEGIN IF ~HashTable.Insert[gMark, ob, $x] THEN RETURN; [] _ CDDirectory.EnumerateChildObjects[ob, EachChild]; WITH ob.specific SELECT FROM cptr: CD.CellSpecific => { name: Rope.ROPE _ CDDirectory.Name[ob, design]; IF name=NIL THEN name _ "UNNAMED"; outputedCellCount _ outputedCellCount+1; cellNameA[outputedCellCount] _ ob; OutCard[outputedCellCount]; OutRopeUpper[name]; OutSize[CDBasics.SizeOfRect[ob.bbox]]; OutCard[20000]; -- count ??? make it big, just in case it is some kind of reference count OutList[cptr.contents, cptr.sequence]; }; rp: CDRepetitions.RepSpecific => NULL; ENDCASE => IF ob.class.composed THEN { TerminalIO.PutRope["?"]; unKnowns_unKnowns+1; }; END; sig: SIGNAL = CODE; OutputDesign: ENTRY PROC [d: CD.Design, s: IO.STREAM] = { ENABLE UNWIND => NULL; MOutputDesign[d, s] }; MOutputDesign: PROC [d: CD.Design, s: IO.STREAM] = BEGIN ENABLE { UNWIND => cellNameA_NIL; PushedState => {GOTO Pushed}; RuntimeError.BoundsFault => { TerminalIO.PutRope["BoundsFault, maybe some feature is not representable for chipmonk; proceed is secure\n"]; SIGNAL sig; GOTO Failed }; RuntimeError.UNCAUGHT => { TerminalIO.PutRope["unknown error, maybe some feature is not representable for chipmonk; proceed is secure\n"]; SIGNAL sig; GOTO Failed }; }; gMark _ HashTable.Create[]; freeAtom _ 1; auxAtom[0] _ [older: 0, younger: 0]; stream _ s; design _ d; unKnowns _ unknownObjects _ unknownAtoms _ 0; cellCount _ outputedCellCount _ 0; [] _ CDDirectory.Enumerate[design, EachEntryCount]; OutCard[codeWordForDataFile]; OutCard[8]; -- version number OutCard[cellCount]; cellNameA _ NEW[ARRAY [0..maxnum) OF CD.Object _ ALL[NIL]]; [] _ CDDirectory.Enumerate[design, EachEntryOutput]; IF outputedCellCount#cellCount THEN ERROR; OutPushedLevels[]; OutCard[0]; -- pushed layer 0 OutCard[0]; -- anychanges OutList[design.actual.first.specific.contents]; cellNameA_NIL; IF unKnowns#0 THEN { TerminalIO.PutF1["** unknown features: %g\n", [integer[unKnowns]]]; }; IF unknownObjects#0 THEN { TerminalIO.PutF1["** unknown objects: %g\n", [integer[unknownObjects]]]; }; IF unknownAtoms#0 THEN { TerminalIO.PutF1["** unknown properties or propertynames: %g\n", [integer[unknownAtoms]]]; }; EXITS Pushed => {TerminalIO.PutRope["Output Failed (pushed in cell)\n"]}; Failed => {TerminalIO.PutRope["Output Failed \n"]}; END; OutPushedLevels: PROC [] = BEGIN IF design.actual.rest#NIL THEN { TerminalIO.PutRope["design is in pushed state\n"]; ERROR PushedState }; END; freeAtom: INTEGER _ 1; AuxEntry: TYPE = RECORD [older, younger: INTEGER -- doubly-linked LRU list --]; auxAtom: REF ARRAY [0..atomTableSize] OF AuxEntry = NEW[ARRAY [0..atomTableSize] OF AuxEntry]; atomTableSize: INTEGER = 256; atomTable: REF ARRAY [1..atomTableSize] OF Rope.ROPE -- for short I/O -- = NEW[ARRAY [1..atomTableSize] OF Rope.ROPE]; ToRope: PROC [a: REF ANY] RETURNS [r: Rope.ROPE] = BEGIN IF a=NIL THEN RETURN [NIL]; WITH a SELECT FROM rp: Rope.ROPE => r _ rp; at: ATOM => r _ Atom.GetPName[at]; ENDCASE => {r _ "?Unknown?"; unknownAtoms_unknownAtoms+1}; END; OutAtom: PROC [a: REF ANY] = BEGIN i: INTEGER; r: Rope.ROPE = ToRope[a]; BEGIN FOR i _ auxAtom[0].older, auxAtom[i].older WHILE i#0 DO IF Rope.Equal[r, atomTable[i]] THEN { OutCard[LOOPHOLE[-i, CARDINAL]]; auxAtom[auxAtom[i].older].younger _ auxAtom[i].younger; auxAtom[auxAtom[i].younger].older _ auxAtom[i].older; GOTO Touchi; }; ENDLOOP; IF freeAtom { auxAtom[i].older _ auxAtom[0].older; auxAtom[i].younger _ 0; auxAtom[auxAtom[0].older].younger _ i; auxAtom[0].older _ i; }; END; END; HasSurround: PROC [ob: CD.Object] RETURNS [yes: BOOL_FALSE] = INLINE BEGIN yes _ FALSE END; AngleExt: PROC[tob: CD.Object] RETURNS [CD.Number] = { tp: NMosTransistors.TransistorPtr = NARROW[tob.specific]; RETURN [tp.width+tp.length+tp.wExt-CD.InterestSize[tob].x] }; Size: PROC [ob: CD.Object] RETURNS [CD.Position] = { s: CD.Position _ CDBasics.SizeOfRect[ob.bbox]; IF s.x<0 OR s.y<0 THEN ERROR; RETURN [s] }; InstLoc: PROC [inst: CD.Instance] RETURNS [CD.Position] = INLINE { r: CD.Rect _ IF CDCells.IsCell[inst.ob] THEN CDInstances.InstRectO[inst] ELSE CDInstances.InstRectI[inst]; RETURN [CDBasics.BaseOfRect[r]]; }; OutList: PROC [list: CD.InstanceList, seq: CD.InstanceSequence_NIL] = BEGIN OutProps: PROC [props: CD.PropList] = BEGIN count: CARDINAL _ 0; FOR pl: CD.PropList _ props, pl.rest WHILE pl#NIL DO IF ISTYPE[pl.first.key, ATOM] THEN count _ count+1 ENDLOOP; OutCard[count]; FOR pl: CD.PropList_props, pl.rest WHILE pl#NIL DO IF ISTYPE[pl.first.key, ATOM] THEN { IF pl.first.key=$InstanceName OR pl.first.key=$SignalName THEN { OutCard[1]; OutRope[ToRope[pl.first.val]] } ELSE { OutCard[2]; OutAtom[pl.first.key]; OutAtom[pl.first.val]; } } ENDLOOP; END; OutInst: PROC [i: CD.Instance] RETURNS [BOOL_FALSE] = { OutSize[InstLoc[i]]; OutOrient[i.trans.orient]; OutObject[i.ob, i]; OutProps[i.properties] }; lCnt: INT _ CDInstances.Length[list]; sCnt: INT _ IF seq=NIL THEN 0 ELSE seq.length; OutCard[lCnt+sCnt]; [] _ CDCellsBackdoor.EnumInsts[list, seq, OutInst] END; OutOrient: PROC [o: CD.Orientation] = BEGIN c: CARDINAL = ORD[o]/2*4 + ORD[o] MOD 2; OutCard[c]; END; OutObject: PROC[ob: CD.Object, appForRectProperty: CD.Instance_NIL] = BEGIN OutUnknownObject: PROC[r: Rope.ROPE_NIL] = { IF NOT Rope.IsEmpty[r] THEN TerminalIO.PutRope[r]; unknownObjects_unknownObjects+1; OutCard[0]; }; OutRectObject: PROC[ob: CD.Object] = { x: REF = CDProperties.GetObjectProp[from: ob, prop: $CDxChipmonkThinks]; IF x=$Rext THEN { OutCard[rectangleCode]; OutSize[Size[ob]]; OutLevel[ob.layer]; } ELSE { OutCard[wireCode]; OutSize[Size[ob]]; OutLevel[ob.layer]; } }; IF ob=NIL THEN { OutCard[0]; unKnowns_unKnowns+1; TerminalIO.PutRope["nil/n"]; RETURN; }; WITH ob.specific SELECT FROM cptr: CD.CellSpecific => { cellNum: NAT _ 0; OutCard[instanceCode]; FOR i: NAT IN [1..cellCount] DO IF ob=cellNameA[i] THEN {cellNum_i; EXIT} ENDLOOP; IF cellNum=0 THEN {TerminalIO.PutRope["**bad cell\n"]; unKnowns_unKnowns+1}; OutCard[cellNum]; }; rp: CD.RectSpecific => {OutRectObject[ob]}; tp: NMosTransistors.TransistorPtr => { j: CARDINAL; OutCard[transistorCode]; OutNumber[tp.width]; OutNumber[tp.length]; IF tp.lExt/lambdaFactor>63 OR tp.wExt/lambdaFactor>63 THEN ERROR; j _ tp.lExt/lambdaFactor+tp.wExt/lambdaFactor*64; IF tp.pullup THEN j _ Basics.BITOR[j, 40000B]; IF tp.implant>0 THEN j _ Basics.BITOR[j, 100000B]; IF tp.angle THEN j _ Basics.BITOR[j, 20000B]; IF HasSurround[ob] THEN j _ Basics.BITOR[j, 10000B]; OutCard[j]; IF tp.angle THEN { s: CD.Position = Size[ob]; qq: INTEGER _ MAX[s.y-tp.wExt-tp.length-2*tp.lExt, 0]; --may be out of range OutNumber[qq]; -- angle extension }; IF tp.implant>0 THEN OutCard[tp.implant]; }; cp: NMosContacts.ContactPtr => { j: CARDINAL; s: CD.Position = Size[ob]; ss: CARDINAL _ s.y; OutCard[contactCode]; j _ contactTab[cp.typ]; j _ Basics.BITOR[j, Basics.BITSHIFT[ss, 8]]; OutCard[j]; OutLevel[ob.layer]; OutCard[0]; --surround... IF cp.typ=burr THEN { OutNumber[s.x]; OutCard[Basics.BITOR[Basics.BITSHIFT[cp.wExt, 8], cp.lExt]]; }; }; tp: CDTexts.TextSpecific => { OutRope[tp.text]; TerminalIO.PutRope["text; font information lost\n"]; }; rp: CDRepetitions.RepSpecific => { OutCard[repeatCode]; OutObject[rp.ob]; OutCard[0]; -- w OutCard[0]; -- l OutSize[rp.offset]; OutCard[rp.count]; OutOrient[rp.orientation]; }; ENDCASE => OutUnknownObject["?"]; END; COutputDesign: PROC [comm: CDSequencer.Command] = BEGIN name, fileName: Rope.ROPE; s: IO.STREAM; wDir: Rope.ROPE _ CDIO.GetWorkingDirectory[comm.design]; TerminalIO.PutRope["Chipmonk Output Design\n"]; IF Rope.IsEmpty[wDir] THEN wDir _ FileNames.CurrentWorkingDirectory[]; TerminalIO.PutRope["Chipmonk output file name"]; IF ~Rope.IsEmpty[wDir] THEN { TerminalIO.PutRopes[" (", wDir, ")"]; }; name _ TerminalIO.RequestRope[" > "]; fileName _ CDIO.MakeName[name, "chip"]; IF ~Rope.IsEmpty[wDir] THEN fileName _ FS.ExpandName[fileName, wDir].fullFName; s _ FS.StreamOpen[fileName, create ! FS.Error => IF error.group#bug THEN { TerminalIO.PutRope[error.explanation]; GOTO FileIOOpenFailed; } ]; CDOps.DeselectAll[design: comm.design, setSelection: TRUE]; TransformSelected[comm.design, rotate180X]; OutputDesign[comm.design, s]; IO.Close[s]; TransformSelected[comm.design, rotate180X]; CDOps.DeselectAll[design: comm.design]; TerminalIO.PutRope[" end output\n"]; EXITS FileIOOpenFailed => {TerminalIO.PutRope["Open Failed\n"]}; END; levelTab[NMos.cut] _ 0; levelTab[NMos.dif] _ 1; levelTab[NMos.pol] _ 2; levelTab[NMos.met] _ 3; levelTab[NMos.imp] _ 4; levelTab[NMos.ovg] _ 5; levelTab[NMos.bur] _ 6; levelTab[NMos.cut2] _ 8; levelTab[NMos.met2] _ 11; levelTab[NMos.cut2] _ 15; contactTab[burr] _ 4; contactTab[mDif] _ 1; contactTab[butt] _ 3; contactTab[mPol] _ 2; contactTab[mm2] _ 5; CDSequencer.ImplementCommand[$ChipmonkOutput, COutputDesign]; CDCommandOps.RegisterWithMenu[$IOMenu, "chipmonk-output", "certain technologies only", $ChipmonkOutput, COutputDesign, doQueue, NMos.nmos]; END. ^ChipmonkNMosWrite.mesa Copyright c 1984, 1986 by Xerox Corporation. All rights reserved. Last edited by: Christian Jacobi, February 20, 1984 12:06 pm Last edited by: Christian Jacobi, February 24, 1987 12:05:53 pm PST --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 -- ignores name parameter, takes name from cell-data itself -- re-arrange LRU queue -- add a new atom RETURN [ob.layer=NMos.pdif] --copied from cmostransistorsimpl --wrp: REF NMos.WellRectRep => {OutRectObject[ob]}; ΚO˜•StartOfExpansionl[r1: ROPE _ NIL, r2: ROPE _ NIL, r3: ROPE _ NIL, r4: ROPE _ NIL, r5: ROPE _ NIL, r6: ROPE _ NIL]šœ™Jšœ Οmœ7™BJšœ<™