<> <> <> <> <> <> <> <> DIRECTORY Basics USING [CompareINT, Comparison], CD USING [Instance, InstanceList, InterestRect, Number, Object, Rect], CDBasics, CDInstances USING [InstRectO], CDProperties USING [GetProp, GetInstanceProp, PutInstanceProp, PutObjectProp], FS USING [StreamOpen], ImagerTransformation USING [Transformation], IO USING [atom, Close, int, PutF, PutFR, PutRope, real, refAny, rope, STREAM, time], PropertyLists USING [GetProp, PropList, PutProp], Real USING [Fix], RedBlackTree USING [Compare, Create, DestroyTable, DuplicateKey, GetKey, Insert, LookupLargest, LookupNextSmaller, Table], RefTab USING [Fetch, Key, Pairs, Ref, Store, Val], Rope USING [Cat, Compare, Fetch, Length, ROPE], SX USING [AreaPerimRec, Circuit, CircuitNode, FindRootNode, MergeRecList, NodeLinkage, NormalizeCircuit], SXAccess USING [design], SXAccessInternal USING [GetLogicalCell], SXOutput USING [outputGeometricInfo, shortestNamesOnly], SXOutputPrivate USING [actualCellInstanceName, actualSignalName, Circuit, CircuitNode, isPort, LogicalCell, MergeRec, MergeRecList, Naming, NodeLinkage, ROPE, ROPEList], UserCredentials USING [Get]; SXOutputImplB: CEDAR PROGRAM IMPORTS Basics, CD, CDBasics, CDInstances, CDProperties, FS, IO, PropertyLists, Real, RedBlackTree, RefTab, Rope, SX, SXAccess, SXAccessInternal, SXOutput, SXOutputPrivate, UserCredentials EXPORTS SXOutputPrivate = BEGIN OPEN SXOutputPrivate; tiptoe: BOOL _ FALSE; ValidMerge: PUBLIC PROC [merge: MergeRec] RETURNS [valid: BOOL] = { valid _ merge.applChain.rest = NIL; }; GetANaming: PUBLIC PROC [thing: REF ANY, insistValid: BOOL _ TRUE] RETURNS [naming: Naming] = { WITH thing SELECT FROM node: REF CircuitNode => { naming _ NARROW[node.properties.GetProp[ actualSignalName]]; }; appl: CD.Instance => { naming _ NARROW[CDProperties.GetInstanceProp[from: appl, prop: actualCellInstanceName]]; }; ENDCASE => ERROR; IF insistValid THEN WHILE naming # NIL AND NOT Valid[naming] DO naming _ naming.next ENDLOOP; }; Valid: PUBLIC PROC [naming: Naming] RETURNS [valid: BOOL] = { valid _ naming.named # NIL; }; GetAName: PUBLIC PROC [thing: REF ANY] RETURNS [name: ROPE] = { naming: Naming _ GetANaming[thing]; name _ IF naming # NIL THEN NamingName[naming] ELSE NIL; }; NamingName: PUBLIC PROC [naming: Naming] RETURNS [name: ROPE] = { name _ naming.name}; HasAskedName: PUBLIC PROC [thing: REF ANY] RETURNS [asked: BOOL] = { FOR naming: Naming _ GetANaming[thing], naming.next WHILE naming # NIL DO IF Valid[naming] AND NamingAsked[naming] THEN RETURN [TRUE]; ENDLOOP; asked _ FALSE; }; NamingAsked: PUBLIC PROC [naming: Naming] RETURNS [asked: BOOL] = { asked _ naming.explicit; }; EnumerateNames: PUBLIC PROC [thing: REF ANY, PerName: PROC [name: ROPE, valid: BOOL], onlyValid: BOOL _ TRUE] = { FOR naming: Naming _ GetANaming[thing, FALSE], naming.next WHILE naming # NIL DO valid: BOOL _ Valid[naming]; IF valid OR NOT onlyValid THEN PerName[NamingName[naming], valid]; ENDLOOP; }; ReverseNamings: PUBLIC PROC [oldFirst: Naming] RETURNS [newFirst: Naming] = { prev: Naming _ oldFirst; cur: Naming _ prev.next; prev.next _ NIL; WHILE cur # NIL DO next: Naming _ cur.next; cur.next _ prev; prev _ cur; cur _ next; ENDLOOP; newFirst _ prev; }; <<>> <> SKey: TYPE = REF Rope.ROPE; -- RedBlackTree.Key SRec: TYPE = RECORD [key: SKey, naming: Naming]; SData: TYPE = REF SRec; -- RedBlackTree.UserData WorstClass: CARDINAL = 8; classes: ARRAY [0 .. WorstClass] OF RedBlackTree.Table; NamKey: RedBlackTree.GetKey = BEGIN RETURN [NARROW [data, SData].key] END; -- NamKey NamComp: RedBlackTree.Compare = BEGIN c: Basics.Comparison; sk: SKey = NARROW [k]; -- name d: SData = NARROW [data]; -- naming c _ Rope.Compare [sk^, d.key^]; IF c = equal THEN BEGIN n1i: INT _ LOOPHOLE [sk^]; n2i: INT _ LOOPHOLE [d.key^]; c _ Basics.CompareINT [n1i, n2i]; END; RETURN [c] END; -- NamComp Start: PROCEDURE = <> BEGIN FOR c: CARDINAL IN [0 .. WorstClass] DO classes[c] _ RedBlackTree.Create [getKey: NamKey, compare: NamComp] ENDLOOP END; -- Start SInsert: PROCEDURE [s: RedBlackTree.Table, nam: Naming] RETURNS [duplicate: BOOL] = BEGIN ENABLE RedBlackTree.DuplicateKey => GOTO dupl; sk: SKey _ NEW [Rope.ROPE _ nam.name]; data: SData _ NEW [SRec _ [key: sk, naming: nam]]; RedBlackTree.Insert [s, data, sk]; <> RETURN [FALSE]; EXITS dupl => RETURN [TRUE] END; -- SInsert <<>> SortNamings: PUBLIC PROC [oldFirst: Naming] RETURNS [newFirst: Naming] = { IF oldFirst.next = NIL THEN RETURN [oldFirst]; FOR oldFirst _ oldFirst, newFirst WHILE oldFirst # NIL DO class: CARDINAL _ 0; seeingGen: BOOL _ FALSE; <> lastWasGen, lastWasDash, lastWasAlpha, nextLastWasAlpha: BOOL _ FALSE; newFirst _ oldFirst.next; oldFirst.next _ NIL; <> <> FOR i: INT IN [0 .. oldFirst.name.Length[]) DO c: CHAR _ oldFirst.name.Fetch[i]; SELECT c FROM '., '- => IF seeingGen THEN class _ class + 1; ENDCASE; SELECT c FROM '. => {class _ class + 1; seeingGen _ FALSE}; IN ['0 .. '9] => { IF lastWasDash THEN {class _ class + 1; IF seeingGen THEN ERROR}; IF lastWasGen AND NOT nextLastWasAlpha THEN seeingGen _ TRUE; }; ENDCASE => seeingGen _ FALSE; nextLastWasAlpha _ lastWasAlpha; SELECT c FROM '., '- => lastWasAlpha _ FALSE; ENDCASE => lastWasAlpha _ TRUE; SELECT c FROM 'n, 'C, 'Q => {lastWasGen _ TRUE; lastWasDash _ FALSE}; '- => {lastWasGen _ FALSE; lastWasDash _ TRUE}; ENDCASE => lastWasGen _ lastWasDash _ FALSE; ENDLOOP; IF seeingGen THEN class _ class + 1; [] _ SInsert [s: classes[MIN[WorstClass, class]], nam: oldFirst] ENDLOOP; IF newFirst # NIL THEN ERROR; IF SXOutput.shortestNamesOnly THEN { FOR c: CARDINAL IN [0 .. WorstClass] DO sNaming: SData _ NARROW [RedBlackTree.LookupLargest[classes[c]]]; foundValid: BOOL _ FALSE; WHILE (sNaming # NIL) AND (sNaming.naming # NIL) DO foundValid _ foundValid OR Valid[sNaming.naming]; sNaming.naming.next _ newFirst; newFirst _ sNaming.naming; sNaming _ NARROW [RedBlackTree.LookupNextSmaller[classes[c], sNaming.key]]; ENDLOOP; RedBlackTree.DestroyTable [self: classes[c]]; IF foundValid THEN { FOR d: CARDINAL IN (c .. WorstClass] DO RedBlackTree.DestroyTable [self: classes[d]] ENDLOOP; EXIT; } ENDLOOP; } ELSE { FOR c: CARDINAL DECREASING IN [0 .. WorstClass] DO sNaming: SData _ NARROW [RedBlackTree.LookupLargest[classes[c]]]; WHILE (sNaming # NIL) AND (sNaming.naming # NIL) DO sNaming.naming.next _ newFirst; newFirst _ sNaming.naming; sNaming _ NARROW [RedBlackTree.LookupNextSmaller[classes[c], sNaming.key]]; ENDLOOP; RedBlackTree.DestroyTable [self: classes[c]] ENDLOOP; }; IF newFirst = NIL THEN ERROR; }; PrintNaming: PUBLIC PROC [to: IO.STREAM, naming: Naming, insert: ROPE _ NIL] = { nth: CARDINAL _ 0; FOR naming _ naming, naming.next WHILE naming # NIL DO IF Valid[naming] THEN { SELECT nth FROM =0 => NULL; =1 => to.PutRope[" (A ("]; >1 => to.PutRope[" ("]; ENDCASE => ERROR; to.PutF["\"%q\"", IO.rope[NamingName[naming]]]; IF nth = 0 AND insert # NIL THEN to.PutRope[insert]; to.PutRope[IF NamingAsked[naming] THEN " (G D)" ELSE " (G P)"]; SELECT nth FROM =0 => NULL; >0 => to.PutRope[")"]; ENDCASE => ERROR; nth _ nth + 1; }; ENDLOOP; IF nth > 1 THEN to.PutRope[")"]; }; CheckNodeInCircuit: PROC [node: REF CircuitNode, circuit: REF Circuit] = { IF NOT tiptoe THEN RETURN; FOR nl: LIST OF REF CircuitNode _ circuit.nodes, nl.rest WHILE nl # NIL DO IF nl.first = node THEN EXIT; REPEAT FINISHED => ERROR; ENDLOOP; }; CheckMergeDirectory: PROC [circuit: REF Circuit] ~ { CheckMerges: PROC [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN] -- RefTab.EachPairAction -- ~ { bottomNode: REF CircuitNode ~ NARROW[key]; FOR ml: MergeRecList _ NARROW[val], ml.rest WHILE ml # NIL DO bottomCircuit: REF Circuit _ SXAccessInternal.GetLogicalCell[ml.first.applChain.first.ob].circuit; CheckNodeInCircuit[bottomNode, bottomCircuit]; CheckNodeInCircuit[ml.first.becomes, circuit]; ENDLOOP; quit _ FALSE; }; IF tiptoe AND circuit.mergeDirectory#NIL THEN [] _ circuit.mergeDirectory.Pairs[action: CheckMerges]; }; AddIntermediateNodes: PUBLIC PROC [cellList: LIST OF REF LogicalCell] ~ { FOR cl: LIST OF REF LogicalCell _ cellList, cl.rest WHILE cl # NIL DO CheckMergeDirectory[cl.first.circuit]; ENDLOOP; <> FOR cl: LIST OF REF LogicalCell _ cellList, cl.rest WHILE cl # NIL DO circuit: REF Circuit _ cl.first.circuit; PiecifyMerges: PROC [key: RefTab.Key, val: RefTab.Val] RETURNS [quit: BOOLEAN] -- RefTab.EachPairAction -- ~ { bottomNode: REF CircuitNode ~ NARROW[key]; FOR ml: MergeRecList _ NARROW[val], ml.rest WHILE ml # NIL DO IF ml.first.applChain = NIL THEN ERROR; IF ml.first.applChain.rest = NIL THEN bottomNode.properties _ bottomNode.properties.PutProp[prop~ isPort, val~ isPort] ELSE { lowNode: REF CircuitNode _ bottomNode; nextHigherNode: REF CircuitNode; lastQual: LIST OF CD.Instance; highQual: LIST OF CD.Instance; FOR appls: LIST OF CD.Instance _ ml.first.applChain, appls.rest WHILE appls.rest # NIL DO qual: LIST OF CD.Instance ~ LIST[appls.first]; lastStep: LIST OF CD.Instance; parentCircuit: REF Circuit _ SXAccessInternal.GetLogicalCell[appls.rest.first.ob].circuit; [node~ nextHigherNode, rootQualifier~ lastStep] _ SX.FindRootNode[ circuit~parentCircuit, subcircuitNode~lowNode, qualifier~qual, insertIfNotInCircuit~TRUE]; IF lastStep # NIL THEN ERROR; IF nextHigherNode = NIL THEN ERROR; CheckNodeInCircuit[nextHigherNode, parentCircuit]; CheckMergeDirectory[parentCircuit]; lowNode.properties _ lowNode.properties.PutProp[prop~ isPort, val~ isPort]; lowNode _ nextHigherNode; lastQual _ appls.rest; ENDLOOP; [ node~ nextHigherNode, rootQualifier~ highQual] _ SX.FindRootNode[ circuit~ circuit, subcircuitNode~ lowNode, qualifier~ lastQual, insertIfNotInCircuit~ FALSE]; IF highQual = NIL AND nextHigherNode # ml.first.becomes THEN ERROR; IF highQual # NIL AND (highQual.rest # NIL OR highQual.first # lastQual.first) THEN ERROR; lowNode.properties _ lowNode.properties.PutProp[prop~ isPort, val~ isPort]; IF highQual # NIL THEN { newML: MergeRecList ~ LIST[[lastQual, ml.first.becomes]]; <<-- Note circuit must have a mergeDirectory as we are currently enumerating it!>> newML.rest _ NARROW[circuit.mergeDirectory.Fetch[ lowNode].val]; [] _ circuit.mergeDirectory.Store[ lowNode, newML]; } }; ENDLOOP; quit _ FALSE; }; IF circuit.mergeDirectory # NIL THEN { CheckMergeDirectory[circuit]; [] _ circuit.mergeDirectory.Pairs[ action~ PiecifyMerges]; CheckMergeDirectory[circuit]; }; ENDLOOP; <> FOR cl: LIST OF REF LogicalCell _ cellList, cl.rest WHILE cl # NIL DO circuit: REF Circuit = cl.first.circuit; FOR appls: CD.InstanceList _ circuit.subcircuits, appls.rest WHILE appls # NIL DO subcircuit: REF Circuit = SXAccessInternal.GetLogicalCell[appls.first.ob].circuit; FOR nl: LIST OF REF CircuitNode _ subcircuit.nodes, nl.rest WHILE nl # NIL DO IF nl.first.properties.GetProp[ isPort] # NIL THEN { parentNode: REF CircuitNode; qual: LIST OF CD.Instance; [node: parentNode, rootQualifier: qual] _ SX.FindRootNode[circuit: circuit, subcircuitNode: nl.first, qualifier: LIST[appls.first], insertIfNotInCircuit: TRUE]; IF qual#NIL OR parentNode=NIL THEN ERROR; }; ENDLOOP; ENDLOOP; ENDLOOP; }; CleanUp: PUBLIC PROC [cellList: LIST OF REF LogicalCell] ~ { <> <> FOR cl: LIST OF REF LogicalCell _ cellList, cl.rest WHILE cl # NIL DO circuit: REF Circuit _ cl.first.circuit; FOR nl: LIST OF REF CircuitNode _ circuit.nodes, nl.rest WHILE nl # NIL DO nl.first.properties _ nl.first.properties.PutProp[ actualSignalName, NIL].PutProp[ isPort, NIL]; ENDLOOP; FOR appls: CD.InstanceList _ circuit.subcircuits, appls.rest WHILE appls # NIL DO CDProperties.PutInstanceProp[appls.first, actualCellInstanceName, NIL]; ENDLOOP; FOR links: LIST OF REF NodeLinkage _ circuit.linkages, links.rest WHILE links # NIL DO CDProperties.PutInstanceProp[ links.first.source, actualCellInstanceName, NIL]; ENDLOOP; IF undoIntermediates THEN { <> SX.NormalizeCircuit[circuit] }; ENDLOOP; }; undoIntermediates: BOOL _ TRUE; IntTransform: TYPE = RECORD [dxdx, dxdy, dx, dydx, dydy, dy: INT]; PrintRoseInstantiationTransformation: PUBLIC PROC [to: IO.STREAM, appl: CD.Instance] = { IF SXOutput.outputGeometricInfo THEN { t: ImagerTransformation.Transformation _ CDBasics.ImagerTransform[appl.trans]; it: IntTransform _ [dxdx: Real.Fix[t.a], dxdy: Real.Fix[t.b], dx: Real.Fix[t.c], dydx: Real.Fix[t.d], dydy: Real.Fix[t.e], dy: Real.Fix[t.f]]; IF t.a # it.dxdx OR t.b # it.dxdy OR t.c # it.dx OR t.d # it.dydx OR t.e # it.dydy OR t.f # it.dy THEN ERROR; to.PutF[" (t6 %g %g %g", IO.int[it.dxdx], IO.int[it.dxdy], IO.int[it.dx]]; to.PutF[" %g %g %g)", IO.int[it.dydx], IO.int[it.dydy], IO.int[it.dy]]; <> } }; -- end PrintRoseInstantiationTransformation PrintRoseInstanceBounds: PUBLIC PROC [to: IO.STREAM, appl: CD.Instance] = { r: CD.Rect; IF NOT SXOutput.outputGeometricInfo THEN RETURN; r _ CDInstances.InstRectO[appl]; to.PutF[" (bb %g %g %g %g)", IO.real [REAL[r.x1]/SXAccess.design.technology.lambda], IO.real [REAL[r.y1]/SXAccess.design.technology.lambda], IO.real [REAL[r.x2]/SXAccess.design.technology.lambda], IO.real [REAL[r.y2]/SXAccess.design.technology.lambda]]; }; nameCount: INT _ 0; NameTransType: PUBLIC PROC [desWDir: ROPE, obj: CD.Object, dfStream: IO.STREAM, type, mode: ATOM, length, width: CD.Number] RETURNS [name: ROPE] = { cellFileName: ROPE; cellStream: IO.STREAM; name _ NARROW[CDProperties.GetProp[from~obj, prop~dfStream]]; IF name # NIL THEN RETURN; name _ IO.PutFR["%g%g%g", IO.atom[type], IO.atom[mode], IO.int[nameCount _ nameCount + 1]]; CDProperties.PutObjectProp[onto~obj, prop~dfStream, val~name]; cellFileName _ name.Cat[".sch"]; cellStream _ FS.StreamOpen[desWDir.Cat[cellFileName], create]; dfStream.PutF["-- (CellType \"%g\")\n %g\n", IO.rope[name], IO.rope[cellFileName]]; cellStream.PutF[ "-- %g\n\n(CreatingUser %g)\n(CreationTime \"%g\")\n", IO.rope[cellFileName], IO.refAny[UserCredentials.Get[].name], IO.time[]]; cellStream.PutF[ "(CellTypeName %g)\n(EC \"Structure\" \"%g%g\")\n", IO.refAny[name], IO.atom[type], IO.atom[mode]]; IF SXOutput.outputGeometricInfo THEN { b: CD.Rect _ CD.InterestRect[obj]; cellStream.PutF["(scale %g \"lambda\")\n", IO.int[1]]; <> cellStream.PutF[ "(bb %g %g %g %g)\n", IO.real [REAL[b.x1]/SXAccess.design.technology.lambda], IO.real [REAL[b.y1]/SXAccess.design.technology.lambda], IO.real [REAL[b.x2]/SXAccess.design.technology.lambda], IO.real [REAL[b.y2]/SXAccess.design.technology.lambda]]; }; cellStream.PutRope["(Ports (\"gate\" (G D) (IN)) (\"ch1\" (G D) (BIDIR) (EC \"Structure\" \"channel\")) (\"ch2\" (G D) (BIDIR) (EC \"Structure\" \"channel\")) )\n"]; cellStream.PutF["(MOSFETFlavor %g %g)\n", IO.atom[type], IO.atom[mode]]; cellStream.PutF["(MOSFETShape %g %g)\n", IO.real[REAL[length]/SXAccess.design.technology.lambda], IO.real[REAL[width]/SXAccess.design.technology.lambda]]; cellStream.PutF["(PrivateFollows)\n(InsidesUnspecified)\n"]; cellStream.Close[]; }; UnNameTransType: PUBLIC PROC [dfStream: IO.STREAM, linkage: REF SX.NodeLinkage] --SXOutput.LinkageHousekeeper-- = { CDProperties.PutObjectProp[onto~linkage.source.ob, prop~dfStream, val~NIL]; }; Start[]; END. <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <>