<> <> <> <> <> DIRECTORY CD, CDAtomicObjects USING [AtomicObsSpecific, DrawList], CDBasics USING [empty, highposition, minposition, NonEmpty], CDProperties USING [GetInstanceProp], CDSimpleRules USING [MinSpace], CMos USING [lambda, ndif, nwell, pdif, pol, pwell, wndif, wpdif], CMosCMTransistors USING [TransistorPtr], 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], SXCMos USING [ndCh, ndCnstr, ndifSpinifex, pChE, pdCh, pdCnstr, pdifSpinifex, pExnD, pExpD, polCnstr, polSpinifex], SXCMosBasicRules USING [difToPolExtSep, difToPolSep], SXOutput USING [LinkagePrintProc], SXOutputPrivate USING [GetANaming, NameTransType, Naming, PrintNaming, PrintRoseInstantiationTransformation], SXTechnology USING [ESWGrow, NESGrow, PerDrawRectProc, ProcessMosTransistor, WNEGrow, WNGrow], TerminalIO USING [PutRope]; SXCMosTransistorsImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDProperties, CDSimpleRules, CMos, IO, Properties, Rope, SX, SXAtoms, SXCMos, SXOutputPrivate, SXTechnology, TerminalIO EXPORTS SXCMos = BEGIN OPEN SXCMos; 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 CMos.ndif, CMos.pdif => RETURN [diffusion]; CMos.pol => RETURN [polysilicon]; CMos.nwell => { wellNode: REF SX.CircuitNode _ cir.AddRect [lev~ CMos.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 = ob.class.objectType; isNType: BOOL = (ob.layer = CMos.ndif); isNWell: BOOL; difSXLayer: SX.SpinifexLayerIndex; difChannel, exclPol: REF SX.Constraint; sep: CD.Number = SXCMosBasicRules.difToPolSep; extSep: CD.Number = SXCMosBasicRules.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 = CD.InterestRect [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 [ob.specific, CDAtomicObjects.AtomicObsSpecific] THEN FOR geom: CDAtomicObjects.DrawList _ NARROW [ob.specific, CDAtomicObjects.AtomicObsSpecific].rList, geom.rest WHILE geom # NIL DO SELECT geom.first.layer FROM CMos.pol => polList _ CONS [geom.first.r, polList]; CMos.ndif, CMos.pdif => difList _ CONS [geom.first.r, difList]; CMos.nwell, CMos.pwell => {wellRect _ geom.first.r; isNWell _ (geom.first.layer = CMos.nwell)}; ENDCASE => ERROR SX.IllegalConstruct [geom.first.r, "Unknown transistor geometry"]; ENDLOOP ELSE -- an old Chipmonk transistor BEGIN dim: CMosCMTransistors.TransistorPtr; IF NOT ISTYPE [ob.specific, CMosCMTransistors.TransistorPtr] THEN ERROR SX.IllegalConstruct [errorRect, "Unknown transistor geometry"]; dim _ NARROW [ob.specific, CMosCMTransistors.TransistorPtr]; <> length _ dim.length; width _ dim.width; extL _ dim.lExt; extW _ dim.wExt; gateA _ (width + 2*extW) * length; gateP _ (width + 2*extW + length) * 2; sourceA _ drainA _ extL * width; sourceP _ drainP _ 2 * extL + width END; <> SELECT tClass FROM $CTrans, $CWellTrans => -- 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: CMos.pol, dim: polRect, trans: trans]; IF extL > sep THEN -- Add rectangles for poly exclusion BEGIN rect _ difExtRectNorth; rect.y1 _ rect.y1 + sep; [] _ SX.AddBox [cir, polSpinifex, rect, trans, SXTechnology.WNEGrow [extSep], exclPol]; rect _ difExtRectSouth; rect.y2 _ rect.y2 - sep; [] _ SX.AddBox [cir, polSpinifex, rect, trans, SXTechnology.ESWGrow [extSep], exclPol]; END; <> rect _ difExtRectNorth; rect.y2 _ rect.y1+sep; [] _ SX.AddBox [cir: cir, spinifexLayer: polSpinifex, dim: rect, trans: trans, value: polCnstr[pChE]]; rect _ difExtRectSouth; rect.y1 _ rect.y2-sep; [] _ SX.AddBox [cir: cir, spinifexLayer: polSpinifex, dim: rect, trans: trans, value: polCnstr[pChE]]; <> [] _ SX.AddBox [cir: cir, spinifexLayer: difSXLayer, dim: chRect, trans: trans, interestBloat: [dx1: (CDSimpleRules.MinSpace[$CMosA, CMos.ndif, CMos.ndif]/2), dy1: 0, dx2: (CDSimpleRules.MinSpace[$CMosA, CMos.ndif, CMos.ndif]/2), dy2: 0], value: difChannel]; <> sourceNode _ SX.AddBox[cir: cir, spinifexLayer: difSXLayer, dim: difExtRectNorth, trans: trans, interestBloat: SXTechnology.WNEGrow[(CDSimpleRules.MinSpace[$CMosA, CMos.ndif, CMos.ndif]/2)]]; drainNode _ SX.AddBox[cir: cir, spinifexLayer: difSXLayer, dim: difExtRectSouth, trans: trans, interestBloat: SXTechnology.ESWGrow[(CDSimpleRules.MinSpace[$CMosA, CMos.ndif, CMos.ndif]/2)]]; <> IF tClass = $CWellTrans THEN BEGIN l: CD.Layer = IF isNWell THEN CMos.nwell ELSE CMos.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, trans: trans]; wellNode.properties _ Properties.PutProp [propList: wellNode.properties, prop: wellNode, val: wellNode]; END; END; -- case $CTrans $CLTrans, $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: CMos.pol, dim: polHor, trans: trans]; [] _ SX.AddRect [cir: cir, lev: CMos.pol, dim: polVert, trans: trans, 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, trans, 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, trans, 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, trans, SXTechnology.ESWGrow [extSep], exclPol]; -- South rect _ [x1: diffNE.x-d, y1: diffSW.y, x2: diffNE.x, y2: diffNE.y]; [] _ SX.AddBox [cir, polSpinifex, rect, trans, 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, trans: trans, 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, trans: trans, 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, trans: trans, 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, trans: trans, value: polCnstr[pChE]] -- East END; -- ch lead-in <> rect _ polHor; rect.x1 _ rect.x1 + extW; [] _ SX.AddBox [cir: cir, spinifexLayer: difSXLayer, dim: rect, trans: trans, interestBloat: [dx1: (CDSimpleRules.MinSpace[$CMosA, CMos.ndif, CMos.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, trans: trans, interestBloat: [dx1: 0, dy1: 0, dx2: 0, dy2: (CDSimpleRules.MinSpace[$CMosA, CMos.ndif, CMos.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, trans: trans, interestBloat: SXTechnology.WNGrow[(CDSimpleRules.MinSpace[$CMosA, CMos.ndif, CMos.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, trans: trans, interestBloat: SXTechnology.WNGrow[(CDSimpleRules.MinSpace[$CMosA, CMos.ndif, CMos.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, trans: trans, interestBloat: SXTechnology.ESWGrow[(CDSimpleRules.MinSpace[$CMosA, CMos.ndif, CMos.ndif]/2)]]; rect _ [x1: diffNE.x-extL, y1: rect.y2, x2: diffNE.x, y2: diffNE.y]; [] _ SX.AddBox[cir: cir, spinifexLayer: difSXLayer, dim: rect, trans: trans, interestBloat: SXTechnology.NESGrow[(CDSimpleRules.MinSpace[$CMosA, CMos.ndif, CMos.ndif]/2)], value: drainNode]; <> IF tClass = $CWellTrans THEN BEGIN l: CD.Layer = IF isNWell THEN CMos.nwell ELSE CMos.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, trans: trans]; wellNode.properties _ Properties.PutProp [propList: wellNode.properties, prop: wellNode, val: wellNode]; END; END; -- case $CTrans $CMosTransistor, $CMosPTypeTransistor => ERROR SX.IllegalConstruct [errorRect, "This kind of Chipmonk transistors is no longer supported"]; $CMosATransistor, $CMosPTypeATransistor => -- Chipmonk angle transistors BEGIN sourceDrainList: Nodes; sourceDrainCount: INTEGER; [gateNode, sourceDrainList, sourceDrainCount] _ SXTechnology.ProcessMosTransistor[ob, trans, cir, difSXLayer, polSpinifex, difChannel, polCnstr[pChE], (CDSimpleRules.MinSpace[$CMosA, CMos.ndif, CMos.ndif]/2), SXCMosBasicRules.difToPolSep, MapMaterial, cir]; IF sourceDrainCount = 2 THEN { sourceNode _ sourceDrainList.first; drainNode _ sourceDrainList.rest.first; } ELSE { TerminalIO.PutRope [Rope.Cat["Xstr with ", ( SELECT sourceDrainCount FROM 0 => "no", 1 => "only 1", ENDCASE => "more than 2"), " sources/drains not included in circuit description\n" ]]; RETURN } END; -- Chipmonk angle transistors ENDCASE => ERROR SX.IllegalConstruct [errorRect, "Unknown transistor class"]; transistor _ SX.CreateLinkage [cir, NEW[CD.InstanceRep_[ob: ob]], 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 CMos.ndif, CMos.wndif => $n, CMos.pdif, CMos.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 CMos.ndif, CMos.wndif => "ETran[", CMos.pdif, CMos.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.GetInstanceProp [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.PutRope [" $Crystal property must be a rope./n"]; cellStream.PutRope ["];"] }; -- ThymeTransistor END. <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<>>