<> <> DIRECTORY Asserting, CompareDataStructure, CompareOps, CompareTransforms, Convert, IO, List, OrderedSymbolTableRef, Rope, RoseTypes, RoseCreate, SwitchTypes, Transistors; RoseFromStructure: CEDAR PROGRAM IMPORTS Asserting, SO: CompareOps, CT: CompareTransforms, Convert, IO, List, OrderedSymbolTableRef, Rope, RoseCreate, RoseTypes, SwitchTypes, Transistors = {OPEN S: CompareDataStructure, R: RoseTypes; ROPE: TYPE = Rope.ROPE; TransistorFlavor: TYPE = {n, p}; Thresholds: TYPE = REF ThresholdsRep; ThresholdsRep: TYPE = ARRAY TransistorFlavor OF ARRAY Transistors.Mode OF RECORD [weakRatio, strongRatio: REAL]; thresholdsFn: REF ANY _ NEW [ROPE _ "thresholdsFn"]; MergeFromStructure: PROC [design: S.Design, thresholds: Thresholds] = { FOR sct: S.CellType _ CT.FirstCellType[design], CT.NextCellType[sct] WHILE sct # NIL DO cellTypeName: ROPE _ SO.PickAName[sct.names]; oldCellType: R.CellType _ RoseCreate.GetCellType[cellTypeName]; IF oldCellType = NIL THEN ReallyDefineCellType[sct, cellTypeName, thresholds]; ENDLOOP; thresholds _ thresholds; }; DefineCellType: PROC [design: S.Design, cellTypeName: ROPE, thresholds: Thresholds] = { sct: S.CellType _ SO.ToType[design, cellTypeName]; ReallyDefineCellType[sct, cellTypeName, thresholds]; }; SimpleThresholds: PROC [weakRatio: REAL _ 3.0, strongRatio: REAL _ 0.3, pFactor: REAL _ 2.5, dFactor: REAL _ 4.0] RETURNS [thresholds: Thresholds] = { thresholds _ NEW [ThresholdsRep _ ALL[ALL[[weakRatio, strongRatio]]]]; FOR tf: TransistorFlavor IN TransistorFlavor DO thresholds[tf][Depletion].weakRatio _ thresholds[tf][Depletion].weakRatio/dFactor; thresholds[tf][Depletion].strongRatio _ thresholds[tf][Depletion].strongRatio/dFactor; ENDLOOP; FOR tm: Transistors.Mode IN Transistors.Mode DO thresholds[p][tm].weakRatio _ thresholds[p][tm].weakRatio/pFactor; thresholds[p][tm].strongRatio _ thresholds[p][tm].strongRatio/pFactor; ENDLOOP; }; ReallyDefineCellType: PROC [sct: S.CellType, cellTypeName: ROPE, thresholds: Thresholds] = { SO.EnsureParts[sct]; SO.EnsurePorts[sct]; IF SO.ExpansionKnown[sct] THEN { rosePorts: R.Ports _ RosePortsFromStructure[sct]; rct: R.CellType; rct _ RoseCreate.RegisterCellType[ name: cellTypeName, expandProc: ExpandFromStructure, ports: rosePorts, typeData: sct, other: AppendAssertions[sct.otherPublic, sct.otherPrivate]]; sct.otherPrivate _ Asserting.AssertFn1[fn: thresholdsFn, val: thresholds, inAdditionTo: sct.otherPrivate]; }; }; AppendAssertions: PROC [as1, as2: Asserting.Assertions] RETURNS [as: Asserting.Assertions] = TRUSTED {as _ LOOPHOLE[List.Append[LOOPHOLE[as1], LOOPHOLE[as2]]]}; RosePortsFromStructure: PROC [sct: S.CellType] RETURNS [rosePorts: R.Ports] = { strPorts: S.PortS _ sct.ports; rosePorts _ NEW [R.PortsRep[strPorts.length]]; FOR pi: NAT IN [0 .. strPorts.length) DO portName: ROPE _ SO.PickAName[strPorts[pi].names]; isIn: BOOL _ Asserting.Test[$IN, NIL, strPorts[pi].other]; isOut: BOOL _ Asserting.Test[$OUT, NIL, strPorts[pi].other]; isBi: BOOL _ Asserting.Test[$BIDIR, NIL, strPorts[pi].other]; isDird: BOOL _ isIn OR isOut OR isBi; confused: BOOL _ (isIn AND isOut) OR (isOut AND isBi) OR (isBi AND isIn); IF confused THEN SO.Warn[[], "Confused port %g", IO.rope[SO.GlobalPortName[sct, pi]]]; FOR nnl: S.RopeList _ strPorts[pi].netNames, nnl.rest WHILE nnl # NIL DO net: S.Vertex _ NARROW[SO.Lookup[sct.parts, nnl.first]]; IF NOT SO.PickAName[net.names].Equal[portName] THEN ERROR; ENDLOOP; rosePorts[pi] _ [ simple: R.noField, switch: R.noField, name: portName, type: SwitchTypes.bitType, input: isIn OR isBi OR NOT isDird, output: isOut OR isBi OR NOT isDird, XPhobic: FALSE]; ENDLOOP; }; ExpandFromStructure: PROC [thisCell: R.Cell, to: R.ExpansionReceiver] = { sct: S.CellType _ NARROW[thisCell.type.typeData]; thresholds: Thresholds _ NARROW[Asserting.FnVal[fn: thresholdsFn, from: sct.otherPrivate]]; PerNode: PROC [ra: REF ANY] RETURNS [stop: BOOL] = { v: S.Vertex _ NARROW[SO.AntiAlias[ra]]; name: ROPE _ SO.PickAName[v.names]; already: R.Node _ RoseCreate.LookupCellNode[thisCell, name]; stop _ FALSE; IF already # NIL THEN RETURN; SELECT v.class FROM net => { other: Asserting.Assertions _ v.other; xPhobic: BOOL _ Asserting.Test[$XPhobic, NIL, other]; xPhillic: BOOL _ Asserting.Test[$XPhillic, NIL, other]; IF NOT (xPhobic OR xPhillic) THEN other _ Asserting.AssertFn[$XPhillic, NIL, other]; other _ Asserting.AssertFn1[$DesignName, sct.design.name, other]; [] _ to.class.NodeInstance[ erInstance: to.instance, name: name, type: SwitchTypes.bitType, other: other]; }; cell => NULL; ENDCASE => ERROR}; PerCell: PROC [ra: REF ANY] RETURNS [stop: BOOL] = { v: S.Vertex _ NARROW[SO.AntiAlias[ra]]; name: ROPE _ SO.PickAName[v.names]; already: R.Cell _ NARROW[thisCell.components.Lookup[name]]; stop _ FALSE; IF already # NIL THEN RETURN; SELECT v.class FROM net => NULL; cell => { typeName: ROPE; connections: ROPE _ EncodeConnections[v]; isTrans: BOOL; tf: TransistorFlavor; mode: Transistors.Mode; ratio: REAL; [isTrans, tf, mode, ratio] _ TransistorStuff[v.type]; IF isTrans THEN typeName _ Transistors.Transistor[[ strength: SELECT ratio FROM >thresholds[tf][mode].weakRatio => driveWeak, driveStrong, ENDCASE => drive, positive: tf=n, mode: mode ]].name ELSE typeName _ SO.PickAName[v.type.names]; [] _ to.class.CellInstance[ erInstance: to.instance, instanceName: name, typeName: typeName, interfaceNodes: connections, other: v.other]; }; ENDCASE => ERROR}; sct.parts.EnumerateIncreasing[PerNode]; sct.parts.EnumerateIncreasing[PerCell]; }; EncodeConnections: PROC [cell: S.Vertex] RETURNS [connections: ROPE] = { connections _ NIL; FOR e: S.Edge _ cell.firstEdge, e.sides[cell].next WHILE e # NIL DO IF e.sides[cell].v # cell THEN ERROR; IF connections # NIL THEN connections _ connections.Cat[", "]; connections _ connections.Cat[ Convert.RopeFromRope[SO.PickAName[cell.type.ports[e.portIndex].names]], ": ", Convert.RopeFromRope[SO.PickAName[e.sides[net].v.names]] ]; ENDLOOP; }; TransistorStuff: PROC [sct: S.CellType] RETURNS [isTrans: BOOL, flavor: TransistorFlavor, mode: Transistors.Mode, ratio: REAL] = { lora, lenwid: Asserting.Terms; len: REAL _ 2; wid: REAL _ 2; isTrans _ FALSE; flavor _ n; mode _ Enhancement; ratio _ 1.0; lenwid _ Asserting.FnVals[fn: $MOSFETShape, from: sct.otherPublic]; IF lenwid = NIL OR lenwid.rest = NIL OR lenwid.rest.rest # NIL THEN RETURN; WITH lenwid.first SELECT FROM rr: REF REAL => len _ rr^; ri: REF INT => len _ ri^; ENDCASE => SIGNAL R.Warning[IO.PutFR["Ill-formatted assertion ($MOSFETShape %g ..) on %g", IO.refAny[lenwid.first], IO.rope[SO.GlobalCellTypeName[sct]]]]; WITH lenwid.rest.first SELECT FROM rr: REF REAL => wid _ rr^; ri: REF INT => wid _ ri^; ENDCASE => SIGNAL R.Warning[IO.PutFR["Ill-formatted assertion ($MOSFETShape .. %g) on %g", IO.refAny[lenwid.rest.first], IO.rope[SO.GlobalCellTypeName[sct]]]]; ratio _ len/wid; lora _ Asserting.FnVals[fn: $MOSFETFlavor, from: sct.otherPublic]; IF lora = NIL THEN RETURN; IF lora.rest = NIL OR lora.rest.rest # NIL THEN SIGNAL R.Warning[IO.PutFR[ "Ill-formatted assertion %g on %g", IO.refAny[CONS[$MOSFETFlavor, lora]], IO.rope[SO.GlobalCellTypeName[sct]] ]] ELSE { SELECT lora.first FROM $n => flavor _ n; $p => flavor _ p; ENDCASE => SIGNAL R.Warning[IO.PutFR["Illegal $MOSFETFlavor type %g on %g", IO.refAny[lora.first], IO.rope[SO.GlobalCellTypeName[sct]]]]; SELECT lora.rest.first FROM $E => mode _ Enhancement; $D => mode _ Depletion; ENDCASE => SIGNAL R.Warning[IO.PutFR["Illegal $MOSFETFlavor mode %g on %g", IO.refAny[lora.rest.first], IO.rope[SO.GlobalCellTypeName[sct]]]]; }; isTrans _ TRUE; }; }.