<> <> <> <> DIRECTORY CD USING [Instance, InstanceList, Layer, Number, Orientation, Position, Rect], CDAtomicObjects USING [AtomicObsPtr, DrawList], CDBasics USING [empty, highposition, minposition, NonEmpty], CDProperties USING [GetPropFromInstance], CDSimpleRules USING [MinDist], CMosB USING [lambda, ndif, nwell, pdif, pol, pwell, wndif, wpdif], IO USING [char, int, Put, PutF, PutRope, rope], Properties USING [PutProp], Rope USING [Cat, ROPE], SX USING [AddBox, AddRect, AdjustNode, AttachedNode, Circuit, CircuitNode, Constraint, ConversionProc, CreateLinkage, IllegalConstruct, LinkageAttach, NodeLinkage, SpinifexLayerIndex], SXAtoms USING [crystalAttr], SXCMosB USING [ndCh, ndCnstr, ndifSpinifex, pChE, pdCh, pdCnstr, pdifSpinifex, pExnD, pExpD, polCnstr, polSpinifex], SXCMosBBasicRules USING [difToPolExtSep], SXOutput USING [LinkagePrintProc], SXOutputPrivate USING [GetANaming, NameTransType, Naming, PrintNaming, PrintRoseInstantiationTransformation], SXTechnology USING [ESWGrow, NESGrow, PerDrawRectProc, WNEGrow, WNGrow], TerminalIO USING [WriteRope]; SXCMosBTransistorsImpl: CEDAR PROGRAM IMPORTS CDBasics, CDProperties, CDSimpleRules, CMosB, IO, Properties, Rope, SX, SXAtoms, SXCMosB, SXOutputPrivate, SXTechnology, TerminalIO EXPORTS SXCMosB = BEGIN OPEN SXCMosB; Nodes: TYPE = LIST OF REF SX.CircuitNode; MapMaterial: SXTechnology.PerDrawRectProc -- [r: CD.Rect, l: CD.Layer, data: REF ANY] RETURNS [TransistorMaterial] -- ~ { cir: REF SX.Circuit ~ NARROW [data, REF SX.Circuit]; SELECT l FROM CMosB.ndif, CMosB.pdif => RETURN [diffusion]; CMosB.pol => RETURN [polysilicon]; CMosB.nwell => { wellNode: REF SX.CircuitNode _ cir.AddRect [lev~ CMosB.nwell, dim~ r]; wellNode.properties _ Properties.PutProp [wellNode.properties, wellNode, wellNode]; RETURN [nothing]; }; ENDCASE => RETURN [nothing]; }; -- MapMaterial ConvTransistor: PUBLIC SX.ConversionProc = <> <> BEGIN transistor: REF SX.NodeLinkage; gateNode, sourceNode, drainNode, wellNode: REF SX.CircuitNode; tClass: ATOM = inst.ob.class.objectType; isNType: BOOL = (inst.ob.layer = CMosB.ndif); isNWell: BOOL; difSXLayer: SX.SpinifexLayerIndex; difChannel, exclPol: REF SX.Constraint; sep: CD.Number = CDSimpleRules.MinDist[CMosB.ndif, CMosB.pol]; extSep: CD.Number = SXCMosBBasicRules.difToPolExtSep; rect, wellRect: CD.Rect; polList, difList, chList, difListSouth: LIST OF CD.Rect _ NIL; length, width, extL, extW: CD.Number; gateA, gateP, sourceA, sourceP, drainA, drainP: INT; -- ignore perimeter leading into channel errorRect: CD.Rect = inst.ob.class.oldInsideRect[inst.ob]; <> IF isNType THEN {difSXLayer _ ndifSpinifex; difChannel _ ndCnstr[ndCh]; exclPol _ polCnstr[pExnD]} ELSE {difSXLayer _ pdifSpinifex; difChannel _ pdCnstr[pdCh]; exclPol _ polCnstr[pExpD]}; <> wellRect _ CDBasics.empty; IF ISTYPE [inst.ob.specificRef, CDAtomicObjects.AtomicObsPtr] THEN FOR geom: CDAtomicObjects.DrawList _ NARROW [inst.ob.specificRef, CDAtomicObjects.AtomicObsPtr].rList, geom.rest WHILE geom # NIL DO SELECT geom.first.lev FROM CMosB.pol => polList _ CONS [geom.first.r, polList]; CMosB.ndif, CMosB.pdif => difList _ CONS [geom.first.r, difList]; CMosB.nwell, CMosB.pwell => {wellRect _ geom.first.r; isNWell _ (geom.first.lev = CMosB.nwell)}; ENDCASE => ERROR SX.IllegalConstruct [geom.first.r, "Unknown transistor geometry"]; ENDLOOP ELSE ERROR SX.IllegalConstruct [errorRect, "Replace this old Chipmonk transistor"]; <> SELECT tClass FROM $C2Trans, $C2WellTrans => -- straight transistors BEGIN difRect, polRect, chRect, difExtRectNorth, difExtRectSouth: CD.Rect; difRect _ difList.first; polRect _ polList.first; chRect _ [difRect.x1, polRect.y1, difRect.x2, polRect.y2]; difExtRectNorth _ difExtRectSouth _ difRect; difExtRectNorth.y1 _ polRect.y2; difExtRectSouth. y2 _ polRect.y1; length _ polRect.y2 - polRect.y1; width _ difRect.x2 - difRect.x1; extL _ polRect.y1 - difRect.y1; extW _ difRect.x1 - polRect.x1; gateA _ (width + 2*extW) * length; gateP _ (width + 2*extW + length) * 2; sourceA _ drainA _ extL * width; sourceP _ drainP _ 2 * extL + width; <> gateNode _ SX.AddRect [cir: cir, lev: CMosB.pol, dim: polRect, inst: inst, pos: pos, orient: orient]; IF extL > sep THEN -- Add rectangles for poly exclusion BEGIN rect _ difExtRectNorth; rect.y1 _ rect.y1 + sep; [] _ SX.AddBox [cir, polSpinifex, rect, inst, pos, orient, SXTechnology.WNEGrow [extSep], exclPol]; rect _ difExtRectSouth; rect.y2 _ rect.y2 - sep; [] _ SX.AddBox [cir, polSpinifex, rect, inst, pos, orient, SXTechnology.ESWGrow [extSep], exclPol]; END; <> rect _ difExtRectNorth; rect.y2 _ rect.y1+sep; [] _ SX.AddBox [cir: cir, spinifexLayer: polSpinifex, dim: rect, inst: inst, pos: pos, orient: orient, value: polCnstr[pChE]]; rect _ difExtRectSouth; rect.y1 _ rect.y2-sep; [] _ SX.AddBox [cir: cir, spinifexLayer: polSpinifex, dim: rect, inst: inst, pos: pos, orient: orient, value: polCnstr[pChE]]; <> [] _ SX.AddBox [cir: cir, spinifexLayer: difSXLayer, dim: chRect, inst: inst, pos: pos, orient: orient, interestBloat: [dx1: (CDSimpleRules.MinDist[CMosB.ndif, CMosB.ndif]/2), dy1: 0, dx2: (CDSimpleRules.MinDist[CMosB.ndif, CMosB.ndif]/2), dy2: 0], value: difChannel]; <> sourceNode _ SX.AddBox[cir: cir, spinifexLayer: difSXLayer, dim: difExtRectNorth, inst: inst, pos: pos, orient: orient, interestBloat: SXTechnology.WNEGrow[(CDSimpleRules.MinDist[CMosB.ndif, CMosB.ndif]/2)]]; drainNode _ SX.AddBox[cir: cir, spinifexLayer: difSXLayer, dim: difExtRectSouth, inst: inst, pos: pos, orient: orient, interestBloat: SXTechnology.ESWGrow[(CDSimpleRules.MinDist[CMosB.ndif, CMosB.ndif]/2)]]; <> IF tClass = $C2WellTrans THEN BEGIN l: CD.Layer = IF isNWell THEN CMosB.nwell ELSE CMosB.pwell; IF NOT CDBasics.NonEmpty[wellRect] THEN ERROR SX.IllegalConstruct [errorRect, "Well transistor must have a well"]; wellNode _ SX.AddRect [cir: cir, lev: l, dim: wellRect, inst: inst, pos: pos, orient: orient]; wellNode.properties _ Properties.PutProp [propList: wellNode.properties, prop: wellNode, val: wellNode]; END; END; -- case $CTrans $C2LTrans, $CLWellTrans => -- angle transistors BEGIN diffNE: CD.Position _ CDBasics.minposition; diffSW, polSW: CD.Position _ CDBasics.highposition; polHor, polVert: CD.Rect; IF ((polList.first.y2-polList.first.y1) < (polList.rest.first.y2-polList.rest.first.y1)) THEN {polHor _ polList.first; polVert _ polList.rest.first} ELSE {polHor _ polList.rest.first; polVert _ polList.first}; FOR diff: LIST OF CD.Rect _ difList, diff.rest WHILE diff # NIL DO IF (diff.first.x1 <= diffSW.x) AND (diff.first.y1 <= diffSW.y) THEN diffSW _ [diff.first.x1, diff.first.y1]; IF (diff.first.x2 >= diffNE.x) AND (diff.first.y2 >= diffNE.y) THEN diffNE _ [diff.first.x2, diff.first.y2]; ENDLOOP; polSW _ [polHor.x1, polHor.y1]; extW _ diffSW.x - polSW.x; extL _ polSW.y - diffSW.y; length _ polHor.y2 - polHor.y1; width _ ((polHor.x2 - polHor.x1) - extW) + ((polVert.y2 - polVert.y1) - extW) - (length*3/2); gateA _ ((width+length/2) + 2*extW) * length; gateP _ ((polHor.x2 - polHor.x1) + (polVert.y2 - polVert.y1)) * 2; sourceA _ ((diffNE.x - diffSW.x) + (diffNE.y - diffSW.y - extL)) * extL; sourceP _ 2 * extL + (diffNE.x - diffSW.x) + (diffNE.y - diffSW.y); drainP _ diffNE.x + diffNE.y - diffSW.x - diffSW.y - 2 * (extL + length); drainA _ drainP * extL; <> gateNode _ SX.AddRect [cir: cir, lev: CMosB.pol, dim: polHor, inst: inst, pos: pos, orient: orient]; [] _ SX.AddRect [cir: cir, lev: CMosB.pol, dim: polVert, inst: inst, pos: pos, orient: orient, value: gateNode]; IF extL > sep THEN -- Add rectangles for poly exclusion BEGIN d: CD.Number _ extL + length + sep; rect _ [x1: diffSW.x, y1: diffSW.y+d, x2: diffNE.x-d, y2: diffSW.y+length+2*extL]; [] _ SX.AddBox [cir, polSpinifex, rect, inst, pos, orient, SXTechnology.WNGrow [extSep], exclPol]; -- North rect _ [x1: diffNE.x-length-2*extL, y1: diffSW.y+d, x2: diffNE.x-d, y2: diffNE.y]; [] _ SX.AddBox [cir, polSpinifex, rect, inst, pos, orient, SXTechnology.WNGrow [extSep], exclPol]; -- West d _ extL - sep; rect _ [x1: diffSW.x, y1: diffSW.y, x2: diffNE.x, y2: diffSW.y+d]; [] _ SX.AddBox [cir, polSpinifex, rect, inst, pos, orient, SXTechnology.ESWGrow [extSep], exclPol]; -- South rect _ [x1: diffNE.x-d, y1: diffSW.y, x2: diffNE.x, y2: diffNE.y]; [] _ SX.AddBox [cir, polSpinifex, rect, inst, pos, orient, SXTechnology.NESGrow [extSep], exclPol] -- East END; -- poly excl <> BEGIN d: CD.Number _ extL + length + sep; rect _ [x1: diffSW.x, y1: diffSW.y+extL+length, x2: diffNE.x-extL-length, y2: diffSW.y+d]; [] _ SX.AddBox [cir: cir, spinifexLayer: polSpinifex, dim: rect, inst: inst, pos: pos, orient: orient, value: polCnstr[pChE]]; -- North rect _ [x1: diffNE.x-d, y1: diffSW.y+extL+length, x2: diffNE.x-extL-length, y2: diffNE.y]; [] _ SX.AddBox [cir: cir, spinifexLayer: polSpinifex, dim: rect, inst: inst, pos: pos, orient: orient, value: polCnstr[pChE]]; -- West d _ extL - sep; rect _ [x1: diffSW.x, y1: diffSW.y+d, x2: diffNE.x-d, y2: diffSW.y+extL]; [] _ SX.AddBox [cir: cir, spinifexLayer: polSpinifex, dim: rect, inst: inst, pos: pos, orient: orient, value: polCnstr[pChE]]; -- South rect _ [x1: diffNE.x-extL, y1: diffSW.y+d, x2: diffNE.x-d, y2: diffNE.y]; [] _ SX.AddBox [cir: cir, spinifexLayer: polSpinifex, dim: rect, inst: inst, pos: pos, orient: orient, value: polCnstr[pChE]] -- East END; -- ch lead-in <> rect _ polHor; rect.x1 _ rect.x1 + extW; [] _ SX.AddBox [cir: cir, spinifexLayer: difSXLayer, dim: rect, inst: inst, pos: pos, orient: orient, interestBloat: [dx1: (CDSimpleRules.MinDist[CMosB.ndif, CMosB.ndif]/2), dy1: 0, dx2: 0, dy2: 0], value: difChannel]; rect _ polVert; rect.y2 _ rect.y2 - extW; [] _ SX.AddBox [cir: cir, spinifexLayer: difSXLayer, dim: rect, inst: inst, pos: pos, orient: orient, interestBloat: [dx1: 0, dy1: 0, dx2: 0, dy2: (CDSimpleRules.MinDist[CMosB.ndif, CMosB.ndif]/2)], value: difChannel]; <> rect _ [x1: diffSW.x, y1: diffSW.y+extL+length, x2: diffNE.x-extL-length, y2: diffSW.y+2*extL+length]; sourceNode _ SX.AddBox [cir: cir, spinifexLayer: difSXLayer, dim: rect, inst: inst, pos: pos, orient: orient, interestBloat: SXTechnology.WNGrow[(CDSimpleRules.MinDist[CMosB.ndif, CMosB.ndif]/2)]]; IF difList.rest # NIL THEN -- supposed source is concave BEGIN rect _ [x1: diffNE.x-length-2*extL, y1: rect.y1, x2: rect.x2, y2: diffNE.y]; [] _ SX.AddBox [cir: cir, spinifexLayer: difSXLayer, dim: rect, inst: inst, pos: pos, orient: orient, interestBloat: SXTechnology.WNGrow[(CDSimpleRules.MinDist[CMosB.ndif, CMosB.ndif]/2)], value: sourceNode] END; rect _ [x1: diffSW.x, y1: diffSW.y, x2: diffNE.x, y2: diffSW.x+extL]; drainNode _ SX.AddBox[cir: cir, spinifexLayer: difSXLayer, dim: rect, inst: inst, pos: pos, orient: orient, interestBloat: SXTechnology.ESWGrow[(CDSimpleRules.MinDist[CMosB.ndif, CMosB.ndif]/2)]]; rect _ [x1: diffNE.x-extL, y1: rect.y2, x2: diffNE.x, y2: diffNE.y]; [] _ SX.AddBox[cir: cir, spinifexLayer: difSXLayer, dim: rect, inst: inst, pos: pos, orient: orient, interestBloat: SXTechnology.NESGrow[(CDSimpleRules.MinDist[CMosB.ndif, CMosB.ndif]/2)], value: drainNode]; <> IF tClass = $CWellTrans THEN BEGIN l: CD.Layer = IF isNWell THEN CMosB.nwell ELSE CMosB.pwell; IF NOT CDBasics.NonEmpty[wellRect] THEN ERROR SX.IllegalConstruct [errorRect, "Well transistor must have a well"]; wellNode _ SX.AddRect [cir: cir, lev: l, dim: wellRect, inst: inst, pos: pos, orient: orient]; wellNode.properties _ Properties.PutProp [propList: wellNode.properties, prop: wellNode, val: wellNode]; END; END; -- case $CTrans ENDCASE => ERROR SX.IllegalConstruct [errorRect, "Unknown transistor class"]; transistor _ SX.CreateLinkage [cir, inst, length, width]; <> SX.AdjustNode [node: gateNode, layer: polSpinifex, area: gateA, perim: gateP, mode: absolute]; SX.AdjustNode [sourceNode, difSXLayer, sourceA, sourceP, absolute]; SX.AdjustNode [drainNode, difSXLayer, drainA, drainP, absolute]; SX.LinkageAttach [link: transistor, attachType: $Gate, node: gateNode]; SX.LinkageAttach [link: transistor, attachType: $Source, node: sourceNode]; SX.LinkageAttach [link: transistor, attachType: $Drain, node: drainNode] END; -- ConvTransistor RoseTransistor: PUBLIC SXOutput.LinkagePrintProc -- [desWDir: ROPE, dfStream, cellStream: IO.STREAM, linkage: REF NodeLinkage, name: Rope.ROPE, PrintNode: NodePrintProc] -- ~ { PrintAttachment: PROCEDURE [key: ATOM, portName: Rope.ROPE] ~ { cellStream.Put [IO.rope[" (\""], IO.rope[portName], IO.rope["\" "]]; FOR attachments: LIST OF REF SX.AttachedNode _ linkage.nodes, attachments.rest WHILE attachments # NIL DO IF attachments.first.attachmentType = key THEN { PrintNode[cellStream, attachments.first.node]; cellStream.PutRope[")"]; RETURN } ENDLOOP; cellStream.PutRope ["\"?\")"]; }; -- PrintAttachment naming: SXOutputPrivate.Naming _ SXOutputPrivate.GetANaming [linkage.source]; cellStream.PutRope["(CI "]; SXOutputPrivate.PrintNaming[ cellStream, naming, Rope.Cat[" \"", SXOutputPrivate.NameTransType[ desWDir: desWDir, obj: linkage.source.ob, dfStream: dfStream, type: SELECT linkage.source.ob.layer FROM CMosB.ndif, CMosB.wndif => $n, CMosB.pdif, CMosB.wpdif => $p, ENDCASE => $funny, mode: $E, length: linkage.l, width: linkage.w], "\""] ]; SXOutputPrivate.PrintRoseInstantiationTransformation[cellStream, linkage.source]; cellStream.PutRope [" (CIC"]; PrintAttachment [$Gate, "gate"]; PrintAttachment [$Source, "ch1"]; PrintAttachment [$Drain, "ch2"]; cellStream.PutRope ["))"] }; -- RoseTransistor ThymeTransistor: PUBLIC SXOutput.LinkagePrintProc -- [desWDir: ROPE, dfStream, cellStream: IO.STREAM, linkage: REF NodeLinkage, name: Rope.ROPE, PrintNode: NodePrintProc] -- ~ { PrintAttachment: PROCEDURE [key: ATOM] ~ { FOR attachments: LIST OF REF SX.AttachedNode _ linkage.nodes, attachments.rest WHILE attachments # NIL DO IF attachments.first.attachmentType = key THEN { PrintNode[cellStream, attachments.first.node]; RETURN } ENDLOOP; cellStream.Put [IO.char['?]]; }; -- PrintAttachment <> defaultL: INTEGER = 2* propertyValue: REF; cellStream.Put [IO.rope[name], IO.rope[": "]]; cellStream.PutRope [SELECT linkage.source.ob.layer FROM CMosB.ndif, CMosB.wndif => "ETran[", CMosB.pdif, CMosB.wpdif => "CTran[", ENDCASE => "FunnyTran[" ]; PrintAttachment [$Gate]; cellStream.Put [IO.char[',]]; PrintAttachment [$Source]; cellStream.Put [IO.char[',]]; PrintAttachment [$Drain]; cellStream.Put [IO.char['|]]; cellStream.PutF[" W_N*%g", IO.int[linkage.w/ IF linkage.l # defaultL THEN cellStream.PutF[", L_%g", IO.int[linkage.l/ <> propertyValue _ CDProperties.GetPropFromInstance [from: linkage.source, prop: SXAtoms.crystalAttr]; WITH propertyValue SELECT FROM crystalHack: Rope.ROPE => IO.Put [stream: cellStream, v1: IO.rope["; "], v2: IO.rope[crystalHack]]; ENDCASE => IF propertyValue # NIL THEN TerminalIO.WriteRope [" $Crystal property must be a rope./n"]; cellStream.PutRope ["];"] }; -- ThymeTransistor END.